一些需要烂熟于心的代码

Posted arjenlee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些需要烂熟于心的代码相关的知识,希望对你有一定的参考价值。

1、二叉树

1.1、非递归遍历

1.1.1、前序

/**
     * 先序非递归遍历
     * 访问一个节点时候,若该节点左右孩子节点都存在,按照右孩子左孩子顺序压栈,若只存在一个孩子节点,直接压栈该孩子节点
     */
    public void firstTravel(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        //压入根节点
        stack.push(root);
        //栈非空,弹栈遍历该节点,然后
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            System.out.print(node.val + " ");
            if (node.right != null)
                stack.push(node.right);
            if (node.left != null)
                stack.push(node.left);
        }
        System.out.println();
    }

 

1.1.2、中序

 /**
     * 中序非递归遍历
     * 思想:
     * 左-根-右:所以只要左孩子还有左子树就要先遍历左孩子的左子树
     * 1、从根节点开始将左孩子节点压栈,如果左孩子节点还有左子树继续将左孩子节点的左孩子节点压栈,一直这么持续操作,直到遇到null节点;
     * 2、此时栈顶节点就是该树(不特指整棵树)中序遍历第一个要访问的节点,弹出该节点;
     * 3、对该节点的右孩子节点重复1,2操作。
     */
    public void inTravel(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            //一直压入左孩子节点,直到压入null
            if (node != null) {
                stack.push(node);
                //左孩子节点可能为null
                node = node.left;
            }
            //栈顶元素为null就弹栈一次
            else {
                //此时栈顶元素就是以该栈顶元素作为根节点的树的第一个被访问节点
                node = stack.pop();
                System.out.print(node.val + " ");
                //右孩子节点可能为null
                node = node.right;
            }
        }
        System.out.println();
    }

 

1.1.3、后序

/**
     * 后续遍历非递归
     */
    public void lastTravel(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        TreeNode pre = null;//记录上一次访问的节点
        while (!stack.isEmpty() || node != null) {
            //一直压入左孩子节点,直到压入null
            if (node != null) {
                stack.push(node);
                //左孩子节点可能为null,表示
                node = node.left;
            }
            //栈顶元素为null就弹栈一次
            else {
                //此时栈顶元素就是以该栈顶元素作为根节点的树的第一个被访问节点
                node = stack.pop();
                //栈顶节点存在右孩子,且右孩子节点就是上一次被访问的节点
                if (node.right == null || pre == node.right) {
                    System.out.print(node.val + " ");
                    pre = node;//更新状态
                    node = null;
                }
                //没有右孩子或者右孩子没有被访问
                else {
                    stack.push(node);
                    //右孩子节点可能为null
                    node = node.right;
                }
            }
        }
        System.out.println();
    }

 

1.1.4、层次

 public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        //we use LinkedList as a queue
        LinkedList<TreeNode> q = new LinkedList<TreeNode>();
        if(root == null) return res;
        TreeNode p = root;
        q.addLast(p);
        while(!q.isEmpty()){
            int tmpSize = q.size();
            List<Integer> tmpList = new ArrayList<Integer>();
            //Attention:i<tmpSize
            for(int i=0;i<tmpSize;i++){
                p = q.getFirst();
                q.poll();
                tmpList.add(p.val);
                if(p.left!=null)  q.addLast(p.left);
                if(p.right!=null) q.addLast(p.right);
            }
            res.add(tmpList);
        }
        return res;
    }

 

2、排序

2.1、快排

public static int partition(int[] numbers, int low,int high) {
        int temp = numbers[low]; //数组的第一个作为中轴
        while(low < high)  {     
            while(low < high && numbers[high] >= temp) high--;
            numbers[low] = numbers[high];//比中轴小的记录移到低端
            while(low < high && numbers[low] <= temp) low++;
            numbers[high] = numbers[low] ; //比中轴大的记录移到高端
        }
        numbers[low] = temp ; //中轴记录到尾
        return low ; // 返回中轴的位置
    }
public static void quickSort(int[] numbers,int low,int high) {
        if(low < high)   {
          int middle = partition(numbers,low,high); //将numbers数组进行一分为二
          quickSort(numbers, low, middle-1);   //对低字段表进行递归排序
          quickSort(numbers, middle+1, high); //对高字段表进行递归排序
        }    
    }

 

2.2、希尔

int[] arrary = {49, 38, 65, 97, 76, 13, 27, 49, 55, 04};
int[] dk = {5, 3, 1};

public void shellInsert(int[] array, int dk) {
        int temp = 0, j = 0;
        // 遍历所有分组:若元素之间的距离为dk,则为同一个分组
        for (int i = dk; i < array.length; i++) {
            // i,i-dk为同一个分组:对同一个分组的元素进行直接插入排序
            if (array[i] < array[i - dk]) {
                temp = array[i];
                for (j = i - dk; j >= 0 && temp < array[j]; j -= dk) {
                    // 后移dk
                    array[j + dk] = array[j];
                }
                // 定位
                array[j + dk] = temp;
            }
        }
    }

    public void shellSort(int[] array, int[] dk, int t) {
        // 依次按照分组间隔dk进行操作
        for (int i = 0; i < t; i++) {
            shellInsert(array, dk[i]);
        }
    }

 

2.3、归并

public void mergeSort(int[] data) {
        if (data == null || data.length == 0)
            return;
        int len = data.length;
        // 只开辟一次辅助数组
        int[] temp = new int[len];
        mergeSortCore(data, 0, len - 1, temp);
    }
    // 将两个有序子数组合并[start-mid][mid+1,end],并将排序后数组写回原数组
    // temp:辅助数组
    public void merge(int[] data, int start, int mid, int end, int[] temp) {
        //前半段数组[start-mid];后半段数组[mid+1,end];一共为k个元素
        int i = start, j = mid + 1, k = 0;
        //子数组排序结果暂存于辅助数组中
        while (i <= mid && j <= end) {
            if (data[i] < data[j])
                temp[k++] = data[i++];
            else
                temp[k++] = data[j++];
        }
        //前半段数组有剩余
        while (i <= mid)
            temp[k++] = data[i++];
        //后半段数组有剩余
        while (j <= end)
            temp[k++] = data[j++];
        //将排序后的子数组写回原数组
        for (i = 0; i < k; i++)
            data[start + i] = temp[i];
    }
    public void mergeSortCore(int[] data, int start, int end, int[] temp) {
        //递归终止;当数组长度变为1是,停止拆分
        if (start == end)
            return;
        //拆分为左右两个子数组
        int mid = (start + end) / 2;
        mergeSortCore(data, start, mid, temp);//对左侧子数组递归排序;使得左侧子数组有序
        mergeSortCore(data, mid + 1, end, temp);//对右侧子数组递归排序;使得右侧子数组有序
        merge(data, start, mid, end, temp);//合并当前左右有序子数组
    }

 

3、栈

3.1、括号匹配

// 碰到左括号压栈;碰到右括号不压栈,但是判断栈顶元素是否匹配
    public boolean matchJudge(String str) {
        HashMap<Character, Character> dict = new HashMap<>();
        dict.put(‘(‘, ‘)‘);
        dict.put(‘[‘, ‘]‘);
        dict.put(‘{‘, ‘}‘);
        Stack<Character> stack = new Stack();
        boolean res = false;
        int len = str.length();
        //逐个字符
        char ch = ‘‘;
        char p = ‘‘;
        for (int i = 0; i < len; i++) {
            ch = str.charAt(i);
            // 左括号,压栈
            if (dict.containsKey(ch))
                stack.push(ch);
                // 右括号
            else if (dict.containsValue(ch)) {
                // 栈顶元素与右括号匹配
                if (!stack.isEmpty() && dict.get(stack.peek()) == ch)
                    stack.pop();
                    // 不匹配
                else return false;

            }
        }
        return stack.isEmpty() ? true : false;
    }

    //测试数据
    public String getMatchData(int index) {
        String str = "";
        String str1 = "{[(1+2)/(3+4)]-[[(1+2)/(3+4)]]}";
        String str2 = "{[()]}";
        String str3 = "{[]]}";
        String str4 = "[()(]";
        String str5 = "([)]";
        String str6 = "({}[]]])";
        String str7 = "[()](((";
        switch (index) {
            case 1: { str = str1; break; }
            case 2: { str = str2; break; }
            case 3: { str = str3; break; }
            case 4: { str = str4; break; }
            case 5: { str = str5; break; }
            case 6: { str = str6; break; }
            case 7: { str = str7; break; }
        }
        return str;
    }

 3.2、表达式求值

有两个表达式

  (4 + (13 / 5)) = 6        (a)

  ((2 + 1) * 3) = 9    (b)

 public int evalRPN(String[] tokens) {
        int res = 0;
        if (tokens == null || tokens.length == 0)
            return res;
        int len = tokens.length;
        Stack<Integer> stack = new Stack();
        int i = 0;
        for (; i < len; i++) {
            if (isNum(tokens[i]))
                stack.push(Integer.parseInt(tokens[i]));
            else {
                int a = stack.pop();
                int b = stack.pop();
                //除法有顺序要求哦
                stack.push(operator(b, a, tokens[i]));
            }
        }
        if (i == len)
            return stack.pop();
        return res;
    }

    private boolean isNum(String str) {
        boolean b = false;
        try {
            Integer.parseInt(str);
            b = true;
        } catch (Exception e) { }
        return b;
    }

    private int operator(int a, int b, String s) {
        int res = 0;
        switch (s) {
            case "+": { res = a + b; break; }
            case "-": { res = a - b; break; }
            case "*": { res = a * b; break; }
            case "/": { res = a / b; break; }
        }
        return res;
    }

 

以上是关于一些需要烂熟于心的代码的主要内容,如果未能解决你的问题,请参考以下文章

Python从入门到精通Python中字符串的各种骚操作你已经烂熟于心了么?收藏下来就挺好的

Python从入门到精通Python中字符串的各种骚操作你已经烂熟于心了么?收藏下来就挺好的

Spring Boot熟稔于心的20个常识

Introduce Null Object

Css 详细解读定位属性 position 以及参数

Java面试题:Java中的集合及其继承关系