一.算法

1.排序算法

A.选择排序
  • 选择排序就是平常我们生活中最常用的排序算法
  • 选定一个数和数组中其他所以数比较
public static void sortBySelect(int [] arr){
        if(arr==null||arr.length==0){
            return;
        }
        for(int i=0;i<arr.length-1;i++){
            int min = i;
            for(int j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min]){
                    min=j;
                }
            }
            swap(arr,i,min);
        }
    }

    public static void swap(int [] arr,int i,int j){
        int temp = arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
B.冒泡排序
  • 这里我们以从左到右升序为主
  • 先相邻两个比较,若前面的比后面的大交换两个数…经过一轮循环,数组中最大的数就在最后的位置
public static void sortByBubbling(int []nums){
        if(nums==null||nums.length==0){
            return;
        }

        for(int i=0;i<nums.length-1;i++){
            boolean flag = false;//假设没有元素交换
            for(int j=0;j<nums.length-i-1;j++){
                if(nums[j]>nums[j+1]){
                    flag=true;
                    swap(nums,j,j+1);
                }
            }
            if(!flag){//数组已经有序
                break;
            }
        }
        for(int i=0;i<nums.length;i++){
            System.out.println(nums[i]);
        }
    }
C.快速排序
public static void sortByQuick(int [] nums,int i,int j){
        if(nums==null||nums.length==0){
            return;
        }
        if(i<j){
            int index = getIndex(nums,i,j);
            sortByQuick(nums,i,index-1);
            sortByQuick(nums,index+1,j);
        }
    }

    public static int getIndex(int []nums,int i,int j){
        int base = nums[i];
        while(i<j){
           while(i<j&&base<=nums[j]){
               j--;
           }
           nums[i]=nums[j];
           while(i<j&&base>=nums[i]){
               i++;
           }
           nums[j]=nums[i];
        }
        nums[i]=base;
        return i;
    }
4.随机排序
public static void randomSort(int [] nums,int count){
        for(int i=0;i<count;i++){
            int index1=new Random().nextInt(nums.length);
            int index2=new Random().nextInt(nums.length);
            if(index1==index2){
                continue;
            }
            int temp = nums[index1];
            nums[index1]=nums[index2];
            nums[index2]=temp;
        }
    }

2.素数问题

1.素数判断
public static boolean isPrime(int num){
           if(num<2){
               return false;
           }
           for(int i=2;i<=Math.sqrt(num);i++){
               if(num%i==0){
                   return false;
               }
           }
           return true;
 }
2.线性筛
  • 其实就是找到一个素数,把其倍数全部筛掉
public static List<Integer> Prime(int max){
        List<Integer> result = new ArrayList<>();
        boolean [] flags = new boolean[max+1];
        for(int i=0;i<=max;i++){
            flags[i]=true;
        }
        flags[0]=flags[1]=false;
        for(int i=2;i<=max;i++){
            if(flags[i]){
                for(int j=i*2;j<=max;j+=i){
                    flags[j]=false;
                }
            }
        }

        for(int i=2;i<=max;i++){
            if(flags[i]){
                result.add(i);
            }
        }

        return result;
    }

3.判断一个数是否为2的次幂

  • 2的次幂转换成二进制哟弍特点:二进制只有一个1,后面跟了n个0
  • 如果将这个数减去1后发现,仅有的那个1会变为0,而原来的那n个0会变为1
  • 因此可以用与运算来判断
  • 还有种傻一点的做法,对这个数取余和除运算
public static boolean isSecondPow(int num){
        return (num&(num-1))==0;
    }

4.年份问题

  • 给你xxxx年y月z日星期天,问你13个月m天后是星期几,具体是什么时间
  • 这其中夹杂了对闰年的考察
//判断具体日期 未来为星期几很简单 就不多说了
    public static void yearByTime(int year,int month,int date,int gomonth,int godate){
        int [] nowyearinfo = new int[2];//今年的信息 包含当前天数和当前年份总天数
        calDate(year,month,date,nowyearinfo);
        int futureyear = year+(month+gomonth)/12;
        int futuremonth = (month+gomonth)%12;//不一定是这个月
        int futuredate = 0;//未知
        int [] months={31,28,31,30,31,30,31,31,30,31,30,31};
        if((futureyear%4==0&&futureyear%100!=0)||(futureyear%400==0)) {
             months[1]++;
        }
        futuredate = date+godate;
        for(int i=futuremonth-1;futuredate>months[i];i++){
             futuremonth++;
             futuredate-=months[i];
        }
        System.out.println("未来年份为:"+futureyear+"年"+futuremonth+"月"+futuredate+"日");
    }



    private static void calDate(int year, int month, int date,int [] yearinfo) {
        int [] months={31,28,31,30,31,30,31,31,30,31,30,31};
        yearinfo[0] = date;
        if((year%4==0&&year%100!=0)||(year%400==0)) {
            months[1]++;
            yearinfo[1]=366;
        }
        else{
            yearinfo[1]=365;
        }

        for(int i=0;i<month-1;i++){
            yearinfo[0]+=months[i];
        }
    }

5.二分法

  • 适用于已经排序完成了的数据
private static int binarysearch(int [] nums,int key){
         int left=0;
         int right=nums.length-1;
         while(left<=right){
             int mid = (left+right)/2;
             if(nums[mid]==key){
                 return mid;
             }
             else if(key>nums[mid]){
                 left=mid+1;
             }else{
                 right=mid-1;
             }
         }
         return -1;
    }

6.字符串操作

1.字符串翻转
public static String reverse(String str){
         if(str==null||str.length()<=1){
             return str;
         }
         char [] array = str.toCharArray();
         String newstr = "";
         for(int i=array.length-1;i>=0;i--){
             newstr+=array[i];
         }
         return newstr;
    }

7.最大公约数和最小公倍数

//最大公约数
    public static int divisor(int a,int b){
        if(a<b){
            int temp = a;
            a=b;
            b=temp;
        }
        while(b!=0){
            int temp = a%b;
            a=b;
            b=temp;
        }
        return a;
    }

    //最小公倍数 a*b/最大公约数
    public static int multiple(int a,int b){
        int temp = divisor(a,b);
        return ((a*b)/temp);
    }

二.数据结构

1.树

  • 完美二叉树:所有非叶子结点,都有两个子节点,且每一层都被填满了
  • (完)满二叉树:所有非叶子结点,都有两个子节点
  • 完全二叉树:除了最后一层外的每一层必须被填满,且最后一层严格左对齐
  • 平衡二叉树:左右子树深度绝对值相差小于2
A.二叉树
a.二叉树的遍历
  • 前序遍历(根结点-左子结点-右子结点)
public void firstOrder(TreeNode root){
        if(root==null){
            return;
        }
        System.out.println(root.data);
        if(root.leftChild!=null){
            firstOrder(root.leftChild);
        }
        if(root.rightChild!=null){
            firstOrder(root.rightChild);
        }
    }
  • 中序遍历(左子结点-根结点-右子结点)
public void midOrder(TreeNode root){
         if(root==null){
             return;
         }
         if(root.leftChild!=null){
             midOrder(root.leftChild);
         }
        System.out.println(root.data);
         if(root.rightChild!=null){
             midOrder(root.rightChild);
         }
    }
  • 后序遍历(左子结点-右子结点-根结点)
public void postOrder(TreeNode root){
        if(root==null){
            return;
        }
        if(root.leftChild!=null){
            postOrder(root.leftChild);
        }

        if(root.rightChild!=null){
            postOrder(root.rightChild);
        }
        
        System.out.println(root.data);

    }
b.二叉树的最大深度
  • 树的最大深度等于左右子树的最大深度+1
public int maxDepth(TreeNode root){
         if(root==null){
             return 0;
         }
         else{
             return 1+Math.max(maxDepth(root.leftChild),maxDepth(root.rightChild));
         }
    }
c.二叉树的最小深度
public int minDepth(TreeNode root) {
        if(root==null)
            return 0;
        else if(root.leftChild==null && root.rightChild==null)
            return 1;
        else if(root.leftChild!=null && root.rightChild!=null)
            return 1+Math.min(minDepth(root.leftChild), minDepth(root.rightChild));
        else {
            if (root.leftChild != null)
                return 1 + minDepth(root.leftChild);
            else
                return 1 + minDepth(root.rightChild);
        }
    }
d.查找某个数
public TreeNode find(TreeNode root,int key) {
        TreeNode current = root;
        while(current!=null){
             if(current.data>key){
                 current=current.leftChild;
             }else if(current.data<key){
                 current=current.rightChild;
             }else{
                 return current;
             }
        }
        return null;
    }
e.插入
public void insert(TreeNode root,int val){
        TreeNode newNode = new TreeNode(val);
        if(root==null){
            root = newNode;
        }
        else{
            TreeNode current = root;
            TreeNode parent;
            while(current!=null){
                parent = current;
                if(current.data>val){
                    current=current.leftChild;
                    if(current==null){
                        parent.leftChild =newNode;
                        break;
                    }
                }else{
                    current=current.rightChild;
                    if(current==null){
                        parent.rightChild=newNode;
                        break;
                    }
                }
            }
        }
    }
B.红黑树

红黑树基本概念