剑指offer题解Java版

文章目录

3、数组中重复的数字

	public static boolean duplicate(int numbers[],int length,int [] duplication) {
        duplication[0] = -1;
        if(length <=0 || numbers == null) {
            return false;
        }
        for (int i=0; i<numbers.length; i++) {
            if (numbers[i] != i) {
                if (numbers[i] == numbers[numbers[i]]){
                    duplication[0] = numbers[i];
                    return true;
                }
                int temp = numbers[numbers[i]];
                numbers[numbers[i]] = numbers[i];
                numbers[i] = temp;
            }
        }
        return false;
    }

4、二位数组中的查找

	public boolean Find(int target, int [][] array) {
        if (array.length <= 0 || array[0].length <= 0) {
            return false;
        }
        int row = array.length;
        int col = array[0].length;

        int r = 0;
        int c = col-1;
        //注意边界的控制
        while(r <= row-1 && c >= 0){
            if (target == array[r][c]) {
                return true;
            }
            else if (target > array[r][c]) {
                r++;
            }else {
                c--;
            }
        }
        return false;
    }

5、替换空格

public static String replaceSpace(StringBuffer str) {
        int p1 = str.length() - 1;
        for (int i=0, len=str.length(); i<len; i++) {
            if (str.charAt(i) == ' ') {
                str.append("  ");
            }
        }
        int p2 = str.length() - 1;
        while (p1 >= 0 && p2 > p1) {
            if (str.charAt(p1) != ' ') {
                str.setCharAt(p2--, str.charAt(p1--));
            } else {
                str.setCharAt(p2--,'0');
                str.setCharAt(p2--,'2');
                str.setCharAt(p2--,'%');
            }
        }
        return str.toString();

    }

6、从尾到头打印链表

	public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> ret = new ArrayList<>();
        if (listNode != null) {
            ret.addAll(printListFromTailToHead(listNode.next));
            ret.add(listNode.val);
        }
        return ret;
    }

7、重建二叉树

private Map<Integer, Integer> indexForInOrders = new HashMap<>();
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {

        for (int i=0; i<in.length; i++) {
            //键为中序遍历  值是该值的下标
            indexForInOrders.put(in[i],i);
        }
        return reBuildTre(pre,0,pre.length-1,0);
    }

    private TreeNode reBuildTre(int[] pre, int preL, int preR, int inL) {
        if (preL > preR) {
            return null;
        }
        TreeNode root = new TreeNode(pre[preL]);
        int inIndex = indexForInOrders.get(root.val);
        //计算左子树大小  开始时候 找到根节点的位置  减去0 0-root 是根的左子树
        int leftTreeSize = inIndex - inL;
        //preL是根
        root.left = reBuildTre(pre, preL+1, preL+leftTreeSize, inL);
        root.right = reBuildTre(pre,preL+leftTreeSize+1,preR,inL+leftTreeSize+1);
        return root;
    }

8、二叉树的下一个节点

public TreeLinkNode GetNext(TreeLinkNode pNode) {
        if (pNode.right != null) {
            //该节点有右节点 那么右节点的最左节点就是
            TreeLinkNode node = pNode.right;
            while (node.left != null) {
                node = node.left;
            }
            return node;
        } else {
            //该节点没有右节点 那么它是它父节点的左节点吗 是 父节点就是下一个节点
            //                                    否 用父节点代替当前节点 重复前面的判断
            while (pNode.next != null) {
                TreeLinkNode parent = pNode.next;
                if (parent.left == pNode) {
                    return parent;
                }
                pNode = pNode.next;
            }
        }
        return null;
    }

9、用两个栈实现队列

Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() {
        
        if(stack2.isEmpty()) {
           while (!stack1.empty()) {
            stack2.push(stack1.pop());
            } 
        }
        int temp = stack2.pop();
        while (!stack2.empty()) {
            stack1.push(stack2.pop());
        }
        return temp;
    }

10、斐波那契数列

public int Fibonacci(int n) {
        if(n == 0) {
            return 0;
        } else if(n == 2 || n == 1) {
            return 1;
        } else {
            return Fibonacci(n-1) + Fibonacci(n-2);
        }
    }

11、旋转数组中的最小数字

public int minNumberInRotateArray(int [] array) {
        if(array.length == 0 || array == null) {
            return 0;
        }
        int l = 0;
        int h= array.length-1;
        while(l < h) {
            int m =l + (h - l)/2;
            if (array[m] <= array[h]){
                //说明不在这个范围 m-h 但是可能在 l-h
                //45124  l=0 h=4 m=2  
                h = m;
            }else {
                //array[m] > array[h]
                //567123 必定在 m+1 ~ h 中
                l = m+1;
            }
        }
        return array[l];
    }

12、矩阵中的路径

public boolean hasPath(char[] array, int rows, int cols, char[] str) {
        if (rows == 0 || cols == 0) {
            return false;
        }
        boolean[][] marked = new boolean[rows][cols];
        char[][] matrix = buildMatrix(array, rows, cols);
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                //如果backtracking返回ture 那么存在 否则继续试探下一个
                if (backtracking(matrix, str, rows, cols, marked, 0, i, j)) {
                    return true;
                }
            }
        }
        //全部找完,backtracking没找到 不存在
        return false;
    }

    private boolean backtracking(char[][] matrix, char[] str, int rows, int cols,
                                 boolean[][] marked, int pathLen, int r, int c) {

        if (pathLen == str.length) {
            return true;
        }
        if (r < 0 || r >= rows || c < 0 || c >= cols
                || matrix[r][c] != str[pathLen] || marked[r][c]) {
            //matrix[r][c] != str[pathLen] 该字符与要找的不一样
            //marked[r][c] 已经标记过来了 不能重复
            return false;
        }
        //找到了某个字符
        marked[r][c] = true;
        //遍历它的上下左右
        if (backtracking(matrix, str, rows, cols, marked, pathLen+1, r+1, c )
                || backtracking(matrix, str, rows, cols, marked, pathLen+1, r-1, c)
                || backtracking(matrix, str, rows, cols, marked, pathLen+1, r, c-1)
                || backtracking(matrix, str, rows, cols, marked, pathLen+1, r, c+1)) {
            return true;
        }

        //它的上下左右没有路径,那么找到的单个字符没有用,置为false
        marked[r][c] = false;
        return false;
    }

    private char[][] buildMatrix(char[] array, int rows, int cols) {
        char[][] matrix = new char[rows][cols];
        for (int r = 0, idx = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                matrix[r][c] = array[idx++];
            }
        }
        return matrix;
    }

13、机器人的运动范围

递归

public int movingCount(int threshold, int rows, int cols){
        boolean[][] flag = new boolean[rows][cols];
        return calculate(threshold, rows, cols, 0, 0, flag);
    }

    private static int calculate(int threshold, int rows, int cols,
                                 int i, int j, boolean[][] flag) {
        if (i >= rows || i < 0 || j >= cols || j < 0 || flag[i][j]) {
            return 0;
        }

        if (i/10 + i%10 + j/10 + j%10 <= threshold) {
            flag[i][j] = true;
            return calculate(threshold, rows, cols, i - 1, j, flag)
                    + calculate(threshold, rows, cols, i + 1, j, flag)
                    + calculate(threshold, rows, cols, i, j - 1, flag)
                    + calculate(threshold, rows, cols, i, j + 1, flag)
                    + 1;
        } else {
            return 0;
        }
    }

14、剪绳子

public static int max(int n) {
        //小于2的时候 不能再剪了
        if (n < 2) {
            return 0;
        }

        //n等于2的时候 分成1的两段
        if (n == 2) {
            return 1;
        }

        //n等于3的时候 分成 1和2的两段
        if (n == 3) {
            return 2;
        }

        //大于3的时候 尽可能分成长度为3的段
        int t3 = n / 3;

        //此时最后应该剩余4  分成 2*2的两段  而不是 1和3
        if ((n - t3 * 3) == 1) {
            t3 -= 1;
        }

        int t2 = (n - t3 * 3) / 2;

        return (int) Math.pow(3,t3) * (int) Math.pow(2,t2);
    }

15、二进制中1的个数

public int NumberOf1(int n) {
        // 7  0111
        // 6  0110
        // 5  0101
        //一个数 减去1 如果最低位是1  那么这位变为0  7->6
        //           如果最低位是0 找到高位第一个1 变为0 后面变为1 6->5
        //那么 n & n-1 就会把最右边的1变为0
        int count = 0;
        while(n != 0) {
            count++;
            n = n & (n-1);
        }
        return count;
    }

16、数值的整数次方

public double Power(double base, int exponent) {

        if (exponent == 0) {
            return 1;
        }

        if (exponent == 1) {
            return base;
        }

        //用来标记exponent是正数还是负数
        boolean flag = false;
        if (exponent < 0) {
            flag = true;
            exponent = -exponent;
        }

        double pow = Power(base * base, exponent / 2);
        if (exponent % 2 == 1) {
            //奇数次幂要多乘一个
            pow *= base;
        }

        return flag ? 1/pow : pow;
    }

17、打印从1到最大的n位数

private static void printMaxNumOfN(int n) {
        if (n <= 0) {
            return;
        }
        char[] num = new char[n];
        printMaxNumOfN(num, 0);
    }

    private static void printMaxNumOfN(char[] num, int len) {
        if (len == num.length) {
            printNum(num);
            return;
        }

        for (int i=0; i<10; i++) {
            num[len] = (char) (i + '0');
            printMaxNumOfN(num, len + 1);
        }
    }

    /**
     * 打印数字  过滤0
     * @param num
     */
    private static void printNum(char[] num) {
        int index = 0;
        while (index < num.length && num[index] == '0') {
            index++;
        }

        while (index < num.length) {
            System.out.print(num[index++]);
        }
        System.out.println();
    }

18、删除链表节点

/**
     * 在O(1)时间内删除一个节点
     * @param head  头结点
     * @param deleteNode 要删除的节点
     * @return
     */
    public ListNode deleteNode(ListNode head, ListNode deleteNode) {
        if (head == null || deleteNode == null) {
            return null;
        }
        if (deleteNode.next != null) {
            // 要删除的节点不是尾节点
            ListNode next = deleteNode.next;
            deleteNode.val = next.val;
            deleteNode.next = next.next;
        } else {
            if (head == deleteNode) {
                // 只有一个节点
                head = null;
            }
            else {
                ListNode cur = head;
                while (cur.next != deleteNode) {
                    cur = cur.next;
                }
                cur.next = null;
            }
        }
        return head;
    }


    /**
     * 删除链表中的重复节点
     * TODO
     * @param pHead
     * @return
     */
    public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null || pHead.next == null) {
            return pHead;
        }
        ListNode next = pHead.next;
        //头节点是重复值  找到最后一个重复值 删除
        if (pHead.val == next.val) {
            while (next != null && pHead.val == next.val) {
                next = next.next;
            }
            return deleteDuplication(next);
        } else {
            //头节点不是重复值 递归后面的节点
            pHead.next = deleteDuplication(pHead.next);
            return pHead;
        }
    }

19、正则表达式匹配

public static boolean match(char[] str, char[] pattern) {
        if(str == null || pattern == null){
            return false;
        }
        return match(str, 0, pattern, 0);
    }
    private static boolean match(char[] str, int i, char[] pattern, int j){
        //特别注意这里:一定是判断pattern是否遍历完了
        if(pattern.length == j){
            return str.length == i;
        }
        //如果遇到*就是很特殊的情况了
        if(j < pattern.length - 1 && pattern[j+1] == '*'){
            // str --> a  pat --> .*   pattern[j] == '.'
            if(i < str.length && (str[i] == pattern[j] || pattern[j] == '.')){
                //匹配上了,有两条路可以往后走
                        // str --> aa  pat --> a*   str[i] == pattern[j]
                        // 有多个一样   str --> aaa  pat --> a*a  i在第一个a
                return  match(str, i+1, pattern, j)
                        // 但是上面的不能处理 "aaa","a*a" 这样串里的a一直用完了 会留下模式串的a
                        || match(str, i, pattern, j+2);

                // . 匹配任意字符 所以 str[i] == pattern[j] 和 pattern[j] == '.'等价
            } else{
                // str --> a  pat --> b*
                // 没匹配上,那个*就代表其前面的字母使用0次,从j+2开始寻找a
                return match(str, i, pattern, j+2);
            }
        }

        //没遇到*就是最简单的了。
        if(i < str.length && (str[i] == pattern[j] || pattern[j] == '.')){
            return match(str, i+1, pattern, j+1);
        }
        return false;
    }

20、表示数值的字符串

 //"-.123"
    /**
     * [] 字符集合
     * () 分组
     * ? 重复0~1次
     * + 重复1~n次
     * * 重复0~n次
     * . 任意
     * \\. 转义后的.
     * \\d 数字
     * @param str
     * @return
     */
    public boolean isNumeric(char[] str) {

        if (null == str || str.length == 0) {
            return false;
        }

        // [+-]? +-号 出现0或者1次
        // d* 正负号之后 可能出现数字 0或者多  +100 +.
        // // (\\.\\d+)? 出现.  .后面必须有数字数字
        //"1+23" false
        // ([eE][+-]?\d+)* 必须出现e和E 后面才可能出现+- +-后必须出现数字 -1E-16
        return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)*");
    }

21、调整数组顺序使奇数位于偶数前面

public int[] reOrderArray(int [] array) {
        int[] arr = array.clone();
        int j = 0;
        int o = 0;
        for (int i=0; i<array.length; i++) {
            //记录奇数的个数
            if (array[i] % 2 != 0) {
                j++;
            }
        }
        o = j;
        j = 0;
        for(int k=0; k<arr.length; k++) {
            if (arr[k] % 2 == 0){
                array[o++] = arr[k];
            }else {
                array[j++] = arr[k];
            }
        }
        return array;
    }

22、链表中倒数第K个节点

public ListNode FindKthToTail(ListNode head,int k) {
        if (head == null) {
            return null;
        }
        ListNode p = head;
        ListNode q = head;
        while (p != null && k-- > 0) {
            p = p.next;
        }
        //k大于长度  溢出
        if (k > 0) {
            return null;
        }
        //不能这样 如果K大于链表长度  就会溢出
//        for (int i=0; i<k; i++) {
//            p = p.next;
//        }
        while (null != p) {
            p = p.next;
            q = q.next;
        }
        return q;
    }

23、链表中环的入口点

public ListNode EntryNodeOfLoop(ListNode pHead){
        ListNode p1 = pHead;
        ListNode p2 = pHead;

        boolean flag = false;
        while(p1 != null && p2.next != null) {
            p1 = p1.next;
            p2 = p2.next.next;
            if(p1 == p2) {
                flag = true;
                p1 = pHead;
                while(p1 != p2) {
                    p1 = p1.next;
                    p2 = p2.next;
                }
                return p1;
            }
        }
        if(!flag) {
            return null;
        }
        return null;
    }

24、反转链表

public ListNode ReverseList(ListNode head) {
        ListNode newHead = new ListNode(-1);
        
        while (null != head) {
            ListNode node = head.next;
            head.next = newHead.next;
            newHead.next = head;
            head = node;
        }
        return newHead.next;
    }

25、合并两个排序链表

public ListNode Merge(ListNode list1,ListNode list2) {
        if (list1 == null && list2 == null) {
            return null;
        }
        if (list1 == null || list2 == null){
            return list1 == null ? list2 : list1;
        }
        ListNode mergeList = new ListNode(-1);
        ListNode cur = mergeList;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = list1;
                list1 = list1.next;
            }else {
                cur.next = list2;
                list2 = list2.next;
            }
            cur = cur.next;
        }
        if (list1 != null) {
            cur.next = list1;
        }
        if (list2 != null) {
            cur.next = list2;
        }
        return mergeList.next;
    }

26、树的子结构

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 == null || null == root2) {
            return false;
        }
        return isSubTree(root1, root2) 
            || HasSubtree(root1.left, root2) 
            || HasSubtree(root1.right, root2);
    }
    
    private static boolean isSubTree(TreeNode root1, TreeNode root2) {
        if (null == root2) {
            return true;
        }
        if(null == root1) {
            return false;
        }
        if(root1.val != root2.val) {
            return false;
        }
        return isSubTree(root1.left, root2.left) && isSubTree(root1.right, root2.right);
    }

27、二叉树镜像

public void Mirror(TreeNode root) {
        if (root == null) {
            return;
        }
        mirror(root);
        Mirror(root.left);
        Mirror(root.right);

    }

    private void mirror(TreeNode root) {
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
    }

28、对称二叉树

boolean isSymmetrical(TreeNode pRoot){
        if(pRoot == null) {
            return true;
        }

        return isSymmetrical(pRoot.left, pRoot.right);

    }

    private boolean isSymmetrical(TreeNode left, TreeNode right) {
        if(left == null && right == null) {
            return true;
        }

        if(left == null || right == null) {
            return false;
        }

        if(left.val != right.val) {
            return false;
        }

        return isSymmetrical(left.left,right.right) && isSymmetrical(left.right, right.left);
    }

29、顺时针打印矩阵

public ArrayList<Integer> printMatrix(int [][] matrix) {

        //顺序打印行
        int rs = 0;
        //逆序打印行
        int rn = matrix.length - 1;
        //顺序打印列
        int cs = 0;
        //逆序打印列
        int cn = matrix[0].length - 1;
        //标志 原来交换行列
        boolean flag = false;

        ArrayList<Integer> list = new ArrayList<>();

        while (rs <= rn && cs >= cn) {
            if (!flag) {
                //正向打印行列
                for(int i=rs; i<=rn; i++) {
                    list.add(matrix[rs][i]);
                }
                rs++;

                for (int i=cs; i>=cn; i++) {
                    list.add(matrix[i][cs]);
                }
                cs--;
                flag = true;
            } else {
                //逆向打印行列
                for (int i=rn; i>=rs; i--) {
                    list.add(matrix[rn][i]);
                }
                rn--;

                for (int i=cn; i>= cs; i--) {
                    list.add(matrix[i][cn]);
                }
                cn++;
                flag = false;
            }
        }
        return list;
    }

30、包含min函数的栈

private Stack<Integer> dataStack = new Stack<>();
    private Stack<Integer> minStack = new Stack<>();

    public void push(int node) {
        dataStack.push(node);
        minStack.push(minStack.isEmpty() ? node : Math.min(minStack.peek(),node));
    }

    public void pop() {
        dataStack.pop();
        minStack.pop();
    }

    public int top() {
        return dataStack.peek();
    }

    public int min() {
        return minStack.peek();
    }

31、栈的压入弹出序列

public boolean IsPopOrder(int [] pushA,int [] popA) {

        int n = pushA.length;
        Stack<Integer> stack = new Stack<>();
        for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) {
            stack.push(pushA[pushIndex]);
            while (popIndex < n && !stack.isEmpty()
                    && stack.peek() == popA[popIndex]) {
                stack.pop();
                popIndex++;
            }
        }
        return stack.isEmpty();
    }

32、从上到下打印二叉树

public ArrayList<Integer> printFromTopToBottom(TreeNode root) {
        if (null == root) {
            return new ArrayList<>();
        }

        ArrayList<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            list.add(node.val);

            if (null != node.left) {
                queue.offer(node.left);
            }

            if (null != node.right) {
                queue.offer(node.right);
            }
        }
        return list;
    }

33、二叉搜索树的后序遍历序列

public static void main(String[] args) {
        int[] arr1 = {5,7,6,9,11,10,8};
        int[] arr2 = {7,4,6,5};
        Solution s = new Solution();
        System.out.println(s.VerifySquenceOfBST(arr1));
        System.out.println(s.VerifySquenceOfBST(arr2));
    }

    public boolean VerifySquenceOfBST(int [] sequence) {
        if (sequence.length == 0 || null == sequence) {
            return false;
        }
        return subTraversal(sequence, 0, sequence.length - 1);
    }

    private boolean subTraversal(int[] arr, int first, int last) {

        if (last - first <= 1) {
            return true;
        }

        int root = arr[last];
        int index = first;
        while (index < last && arr[index] <= root) {
            index++;
        }

        for (int i=index+1; i<last; i++) {
            if (arr[i] < root) {
                return false;
            }
        }

        return subTraversal(arr, first, index - 1) && subTraversal(arr, index, last - 1);
    }

34、二叉树中和为某一值的路径

ArrayList<ArrayList<Integer>> ret = new ArrayList<>();

    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
        backtracking(root, target, new ArrayList());
        return ret;
    }

    private void backtracking(TreeNode node, int target, ArrayList list) {
        if (null == node) {
            return;
        }


        list.add(node.val);
        target -= node.val;

        //和为target 并且是叶子节点
        if (target == 0 && null == node.right && null == node.left) {
            ret.add(new ArrayList<>(list));
        } else {
            backtracking(node.left, target, list);
            backtracking(node.right, target, list);
        }
        //返回父节点的时候 要删除路径上的当前节点
        list.remove(list.size()-1);
    }

35、复杂链表的赋值

public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null) {
            return null;
        }
        // 插入新节点
        RandomListNode cur = pHead;
        while (cur != null) {
            RandomListNode clone = new RandomListNode(cur.label);
            clone.next = cur.next;
            cur.next = clone;
            cur = clone.next;
        }


        // 建立 random 链接
        cur = pHead;
        while (cur != null) {
            RandomListNode clone = cur.next;
            if (cur.random != null) {
                //看图很直观
                clone.random = cur.random.next;
            }
            cur = clone.next;
        }


        // 拆分
        cur = pHead;
        RandomListNode pCloneHead = pHead.next;
        while (cur.next != null) {
            RandomListNode nextNode = cur.next;
            cur.next = nextNode.next;
            cur = nextNode;
        }


        return pCloneHead;
    }

36、二叉搜索树与双向列表

public TreeNode Convert(TreeNode pRootOfTree) {

        if (null == pRootOfTree) {
            return null;
        }

        TreeNode lastNode = null;
        lastNode = baseConvert(pRootOfTree, lastNode);
        TreeNode head = lastNode;
        while (head.left != null) {
            head = head.left;
        }
        return head;
    }

    public TreeNode baseConvert(TreeNode root, TreeNode lastNode) {
        if (null == root) {
            return lastNode;
        }

        TreeNode cur = root;
        if (cur.left != null) {
            lastNode = baseConvert(cur.left, lastNode);
        }

        cur.left = lastNode;

        if (lastNode != null) {
            lastNode.right = cur;
        }

        lastNode = cur;

        if (cur.right != null) {
            lastNode = baseConvert(cur.right, lastNode);
        }

        return lastNode;
    }

37、序列化二叉树

private String serializeStr;
    String Serialize(TreeNode root) {
        if(null == root) {
            return "$";
        }
        return root.val + "," + Serialize(root.left) + "," + Serialize(root.right);
    }

    TreeNode Deserialize() {
        if(null == serializeStr || serializeStr.length() == 0) {
            return null;
        }

        int index = serializeStr.indexOf(",");
        String node = index == -1 ? serializeStr : serializeStr.substring(0, index);
        serializeStr = index == -1 ? "" : serializeStr.substring(index + 1);
        if (node.equals("$")) {
            return null;
        } else {
            int val = Integer.valueOf(node);
            TreeNode t = new TreeNode(val);
            t.left = Deserialize();
            t.right = Deserialize();
            return t;
        }
    }


    TreeNode Deserialize(String str) {
        serializeStr = str;
        return Deserialize();
    }

38、字符串的排列

public static void main(String[] args) {
        Solution1 s = new Solution1();
        s.Permutation("abc");
    }

    TreeSet<String> ret = new TreeSet<>();
    public ArrayList<String> Permutation(String str) {
        if (null == str) {
            return new ArrayList<>();
        }
        return permutation(str.toCharArray(), 0);
    }

    private ArrayList<String> permutation(char[] chars, int pos) {
        //结束条件  长度==总长  是一个正确的排列了
        if (pos == chars.length - 1) {
            String s = String.valueOf(chars);
            ret.add(s);
        }

        for (int i=pos; i<chars.length; i++) {
            //第i个位置的 和后面的所有进行交换
            char temp = chars[i];
            chars[i] = chars[pos];
            chars[pos] = temp;
            //第i个位置的 和后面的所有进行交换
            permutation(chars, pos+1);

            //  a bcsdf
            // 前面是排列好的那部分 a和其他分别换完之后
            // 再回去它自己的正确位置
            temp = chars[i];
            chars[i] = chars[pos];
            chars[pos] = temp;

        }
        ArrayList<String> list = new ArrayList<>(ret);
        return list;
    }

39、数组中出现次数超过一半的数字

public static int moreThanHalfNum_Solution(int [] arr) {
        if(arr.length == 1) {
            return arr[0];
        }
        int num = arr[0], count = 1;
        for (int i=1,len=arr.length; i<len; i++) {
            if (num == arr[i]) {
                count++;
            } else {
                count--;
            }

            if (count == 0) {
                num = arr[i];
                count = 1;
            }
        }
        //num中保留了可能出现次数最多的数
        int cnt = 0;
        for (int i : arr) {
            if (num == i) {
                cnt++;
            }
        }
        return cnt > arr.length / 2 ? num : 0;
    }

40、最小的K个数

public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        int l = 0, h = input.length - 1;
        ArrayList<Integer> list = new ArrayList<>();
        if(k > input.length) {
            return list;
        }
        while(l < h) {
            int p = partition(input, l, h);
            if(p < k) {
                l = l + 1;
            } else if(p > k) {
                h = h - 1;
            } else {
                break;
            }
        }

        for(int i=0; i<k; i++) {
            list.add(input[i]);
        }
        return list;
    }
    private static int partition(int[] arr, int start, int end) {
        int left = start;
        int right = end;
        int pivot = arr[start];

        while(left < right) {
            while(left < right && arr[right] > pivot) {
                right--;
            }
            while(left < right && arr[left] <= pivot) {
                left++;
            }

            if(left < right) {
                int p = arr[left];
                arr[left] = arr[right];
                arr[right] = p;
            }
        }
        arr[start] = arr[left];
        arr[left] = pivot;
        return left;
    }





    public ArrayList<Integer> getLeastNumbers_Solution(int[] nums, int k) {
        if (k > nums.length || k <= 0) {
            return new ArrayList<>();
        }
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
        for (int num : nums) {
            maxHeap.add(num);
            if (maxHeap.size() > k) {
                maxHeap.poll();
            }
        }
        return new ArrayList<>(maxHeap);
    }

41、数据流中的中位数

/**
     * 左边是大顶堆
     */
    private PriorityQueue<Integer> left = new PriorityQueue<>((o1, o2) -> o2 - o1);

    /**
     * 右边是小顶堆
     */
    private PriorityQueue<Integer> right = new PriorityQueue<>();

    private int N = 0;

    public void Insert(Integer num) {
        //平均分配到两个堆
        if (N % 2 == 0) {
            //左边的原数小  插入元素不一定比左边的小 因此  先插入左边 调整堆 拿出左边最大元素 放入右边
            left.add(num);
            right.add(left.poll());
        } else {
            //同理
            right.add(num);
            left.add(right.poll());
        }
        N++;
    }

    public Double GetMedian() {
        //因为先存在了右边  所以奇数时候  拿出右边的堆顶元素即可
        if (N % 2 == 1) {
            return (double)right.peek();
        } else {
            return (right.peek() + left.peek()) / 2.0;
        }
    }

42、连续子数组的最大和

	public static int FindGreatestSumOfSubArray(int[] arr) {
        if (arr.length == 0) {
            return 0;
        }
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for (int i=0, len=arr.length; i<len; i++) {
            if (sum <= 0) {
                sum = arr[i];
            } else {
                sum += arr[i];
            }
            max = Math.max(sum, max);
        }
        return max;
    }

43、1~n中1出现的次数

参考

/**
     以位数为例,求解百位是1时候的情况
     分为3中情况
     一、百位 >= 2  例如 31256  312-a 56-b
     满足条件的数
     100~199
     1100~1199
     。。
     31100~31999
     百位为1的5位数  (a/10 + 1)* 100
     a/10 + 1   0~31  
     * 100   0~31 每个数的末尾  可以是0~99 共100个

     二、百位为1 例如 31156
     满足条件
     100~199
     1100~1199
     。。。
     30100~30199
     31100~31156
     百位为1的5位数 (a/10)* 100 + (b+1)
     a/10 0~30   31时候 后面是0~b 故 加(b+1)

     三、百位为0   31056
     100~199
     1100~1199
     。。。
     30100~30199
     百位为1的5位数 (a/10)* 100

     百位 >= 2  31256 百位=2  a/10+1 = 31+1  == (a+8)/10 = 320 / 10 = 32
     31343  百位=3 a/10+1 = 31+1  == (a+8)/10 = 321 / 10 = 32

     +8会进位  不需要+1
     故百位 >= 2  || 百位 == 0 ((a+8)/ 10)*100 进位,不需要加1
     百位 == 1 (a+8)/ 10 +(b+1) 不会进位
     */


    private static int numberOf1(int n) {
        int count = 0;
        //从个位开始考虑,再到十位,百位,千位
        for (int i=1; i<=n; i*=10) {
            int a = n/i;
            int b = n%i;
            count += (a + 8) /10 * i + (a % 10 == 1 ? (b+1) : 0);
        }
        return count;
    }

44、数字序列中某一位的数字

private static int indexOf(int index) {
        if (index < 0) {
            return -1;
        }

        if (index <= 9) {
            return index;
        }

        int i = 2;
        index -= 10;
        int n;
        int num;
        while (true) {
            n = i * (int) Math.pow(10,(i-1)) * 9;
            if (index >= n) {
                index -= i * Math.pow(10,(i-1)) * 9;
                i++;
            } else {
                 num = calculateNum(index, i);
                 return num;
            }
        }
    }

    /**
     * 计算是第几个数字 并取出那一位
     * @param index
     * @return
     */
    private static int calculateNum(int index, int i) {
        //m 个i位数
        int m = index / i;
        //第y位
        int y = index % i;
        //前面的数是m  index落在 m+1的第y位
        int num = (int) Math.pow(10,(i-1)) + (m - 1);
        int x = num + 1;

        int c = String.valueOf(x).charAt(y) - '0';
        return c;

    }

45、把数组排成最小的数

public static String PrintMinNumber(int [] numbers) {
        String[] nums = new String[numbers.length];

        for (int i=0, len=numbers.length; i<len; i++) {
            nums[i] = String.valueOf(numbers[i]);
        }

        //最小
        Arrays.sort(nums,(s1,s2) -> (s1 + s2).compareTo(s2 + s1));
        //最大
        //Arrays.sort(nums,(s2,s1) -> (s1 + s2).compareTo(s2 + s1));
        String str = "";
        for (String s : nums) {
            str += s;
        }
        return str;
    }

46、把数字翻译成字符串

/**
     * 0翻译成“a”,1翻译成“b”…25翻译成“z”
     * @param str
     * @return
     */
    public static int numCount(String str) {
        int n = str.length();
        int[] dp = new int[n+1];
        dp[n] = 1;
        for (int i=n-1; i>=1; i--) {
            if (i == n-1) {
                dp[i] = dp[i+1] + calculate(String.valueOf(str), i) * 1;
                continue;
            }
            dp[i] = dp[i+1] + calculate(String.valueOf(str), i) * dp[i+2];
        }
        return dp[1];
    }

    /**
     * 当前与前面能否组合  09 不能组合 56不能组合。。。
     * @param str
     * @param i
     * @return
     */
    private static int calculate(String str, int i) {
        int num = Integer.valueOf(String.valueOf(str.charAt(i-1)) + String.valueOf(str.charAt(i)));
        if (num >= 10 && num <= 25) {
            return 1;
        } else {
            return 0;
        }
    }


    /**
     * 'A' -> 1
     * 'B' -> 2
     * ...
     * 'Z' -> 26
     * @param s
     * @return
     */
    public int numDecodings(String s) {
        if (null == s || s.length() == 0) {
            return 0;
        }

        int n = s.length();
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = s.charAt(0) == '0' ? 0 : 1;
        // substring 不含尾
        for (int i = 2; i <= n; i++) {
            int one = Integer.valueOf(s.substring(i - 1, i));
            if (one != 0) {
                dp[i] += dp[i - 1];
            }
            if (s.charAt(i - 2) == '0') {
                continue;
            }
            int two = Integer.valueOf(s.substring(i - 2, i));
            if (two <= 26) {
                dp[i] += dp[i - 2];
            }
        }
        return dp[n];
    }

47、礼物的最大价值

	/**
     * getMost(i,j) = max(getMost(i-1,j),getMost(i,j-1)) + bord[i][j]
     * 由此可见 跟本次计算有关的值只是前面一行的 那么 可以用一个一维数组来保存前面计算的最值
     * j设置为中坐标  前面j个  (i,0) (i,1) (i,2)...(i,j-1) 保存本行前面的最大值
     *       (i-1,j) (i-1,j+1) (i-1,j+2) ... (i-1,n-1) 保存上一行的最大值
     */
    public int getMost(int[][] board) {
        if (null == board || board[0].length == 0 || board.length == 0) {
            return 0;
        }

        int n = board[0].length;
        int[] max = new int[n];
        for (int[] v : board) {
            max[0] += v[0];
            for (int i=1; i<n; i++) {
                max[i] = Math.max(max[i], max[i-1]) + v[i];
            }
        }
        return max[n-1];
    }

48、最长不含重读字符的子字符串

	public static int longSubStrNoDuplicateChar(String str) {
        int curLen = 0, maxLen = 0;
        // 用来保存每个字符在前面出现的位置
        int[] preChar = new int[26];
        // 初始化所有值为-1
        Arrays.fill(preChar, -1);

        for (int curIndex=0; curIndex<str.length(); curIndex++) {
            // a-0  b-1 c-2 记录字符出现的位置 preChar[0]放置a最近出现的位置 以此类推
            int c = str.charAt(curIndex) - 'a';
            // 当前字符第一次出现的位置
            int preIndex = preChar[c];

            if (c == -1 || curIndex - preIndex > curLen) {
                // 该字符之前没有出现  或者虽然出现了 但是不在最长子串中
                // 例如 abacadb  cad+b 之前的b不构成影响
                curLen++;
            } else {
                maxLen = Math.max(maxLen, curLen);
                curLen = curIndex - preIndex;
            }
            // 更新字符最近出现的位置 abacadb  a由0->2->4
            preChar[c] = curIndex;
        }
        return Math.max(maxLen, curLen);
    }

49、丑数

public static int GetUglyNumber_Solution(int N) {
        //1  2  3  4  5  6      8
        if (N <= 6) {
            return N;
        }
        int i2 = 0, i3 = 0, i5 = 0;
        int[] dp = new int[N];
        dp[0] = 1;
        for (int i = 1; i < N; i++) {
            // 下一个丑数 肯定是前面的丑数乘  2 || 3 || 5 得到的  因为需要排序,所以需要最小的那个
            int next2 = dp[i2] * 2, next3 = dp[i3] * 3, next5 = dp[i5] * 5;
            dp[i] = Math.min(next2, Math.min(next3, next5));

            if (dp[i] == next2) {
                // dp[i] == next2 那么 dp[i2] * 2 已经是最小的了
                // 说明前面的在不需要再计算了 因为它不会大于 dp[i2] * 2 说明已经在数组中了
                i2++;
            }
            if (dp[i] == next3) {
                // 同理
                i3++;
            }
            if (dp[i] == next5) {
                // 同理
                i5++;
            }
        }
        return dp[N - 1];
    }

50、第一个只出现一次的字符

public int FirstNotRepeatingChar(String str) {
        int[] arr = new int[256];
        for(int i=0, len=str.length(); i<len; i++) {
            arr[str.charAt(i)]++;
        }
        
        for(int i=0, len=str.length(); i<len; i++) {
            if(arr[str.charAt(i)] == 1) {
                return i;
            }
        }
       
        return -1;
    }

51、数组中的逆序对

//需要用long
    long count = 0;
    int[] temp;
    
    public int InversePairs(int[] nums) {
        temp = new int[nums.length];
        mergeSort(nums, 0, nums.length-1);
        return (int) (count % 1000000007);
    }
    
    private void mergeSort(int[] arr, int l, int h) {
        if(l >= h) {
            return;
        }
        int m = l + (h - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m+1, h);
        merge(arr, l, m, h);
    }
    
    private void merge(int[] nums, int l, int m, int h) {
        int i=l, k=l, j=m+1;
        
        while(i<=m || j<=h) {
            if(i > m) {
                // 右边有数据
                temp[k] = nums[j++]; 
            } else if(j > h) {
                // 左边有数据
                temp[k] = nums[i++];
            } else if(nums[i] <= nums[j]) {
                // 没有逆序对
                temp[k] = nums[i++];
            } else {
                // nums[i] > nums[j]  那么nums[i]..nums[m] 都大于nums[j]
                temp[k] = nums[j++];
                count += m - i + 1;
            }
            k++;
        }
        // 调整数组 直到有序
        for (k=l; k<=h; k++) {
            nums[k] = temp[k];
        }
    }

52、两个链表的第一个公共节点

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode l1 = pHead1;
        ListNode l2 = pHead2;
        while(l1 != l2) {
            l1 = (l1 == null) ? pHead2 : l1.next;
            l2 = (l2 == null) ? pHead1 : l2.next;
        }
        
        return l1;
    }

53、在排序数组中查找数字

	public int GetNumberOfK(int[] nums, int K) {
        int first = binarySearch(nums, K);
        int last = binarySearch(nums, K + 1);
        return (first == nums.length || nums[first] != K) ? 0 : last - first;
    }

    private int binarySearch(int[] nums, int K) {
        int l = 0, h = nums.length-1;
        while (l <= h) {
            int m = l + (h - l) / 2;
            if (nums[m] >= K) {
                h = m - 1;
            } else {
                l = m + 1;
            }
        }
        return l;
    }

54、二叉搜索树的第K大节点

private TreeNode result;
    private int count = 0;


    public TreeNode KthNode(TreeNode pRoot, int k) {
        inOrder(pRoot, k);
        return result;
    }

    private void inOrder(TreeNode root, int k) {
        if (null == root || count >= k) {
            return;
        }

        inOrder(root.left, k);
        count++;
        if (count == k) {
            result = root;
        }
        inOrder(root.right, k);
    }

55、二叉树的深度

public int TreeDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return Math.max(TreeDepth(root.left),TreeDepth(root.right)) + 1;
    }

56、数组中数字出现的次数

//一个数字出现一次  其他数字出现3次
private static int getOne(int[] arr) {
        int[] bitNum = new int[32];

        for (int i=0, len=arr.length; i<len; i++) {
            int bitMask = 1;
            for (int j=31; j>=0; j--) {
                //看该位置的数是0还是1
                int bit = arr[i] & bitMask;
                if (bit != 0) {
                    //如果是1 就加1
                    bitNum[j]++;
                }
                 //左移一位
                 bitMask <<= 1;
            }
        }
        int result = 0;
        for (int i=0; i<32; i++) {
            result = result << 1;
            result += bitNum[i] % 3;
        }
        return result;
    }
//只出现一次的两个数
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {

        int diff = 0;
        for (int i : array) {
            //结果为2个不相同数的异或结果
           diff ^= i;
        }
        //负数 原码 -> 反码 -> 加一
        // 5    0000 0101
        // 7    0000 0111
        // 5^7  0000 0010 结果是2

        // 2     0000 0010
        // 反码  1111 1101
        // 加一  1111 1110
        // -2   1111 1110  0000 0010
        // 2&-2 0000 0010
        // 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位
        diff &= -diff;

        for (int i : array) {
            //i的低位是0
            if ((i & diff) == 0) {
                num1[0] ^= i;
            } else {
                num2[0] ^= i;
            }
        }
    }

57、和为s的数字

//和为s的两个数字
public ArrayList<Integer> findNumbersWithSum(int [] array, int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        if(array.length == 0 || null == array) {
            return list;
        }
        int l = 0, h = array.length-1;
        while(l < h) {
            int mid = l + (h - l) / 2;
            int t = array[l] + array[h];
            if(t > sum) {
                h--;
            } else if(t < sum) {
                l++;
            } else {
                list.add(array[l]);
                list.add(array[h]);
                break;
            }
        }
        return list;
    }
//和为s的连续正序列
public ArrayList<ArrayList<Integer>> findContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
        int small = 1;
        int big = 2;
        //至少两个数字  所以小的不能大于和的一半
        int stop = (1+sum)/2;
        int target = 3;
        while(small < stop) {
            if(target < sum) {
                big++;
                target += big;
            } else if(target > sum) {
                target -= small;
                small++;
            }  else {
                ArrayList<Integer> list = new ArrayList<>();
                for(int i=small; i<=big; i++) {
                    list.add(i);
                }
                ret.add(list);
                big++;
                target += big;
            }
        }
        return ret;
    }

58、反转字符串

public static String ReverseSentence(String str) {
        char[] chars = str.toCharArray();
        int n = str.length();
        //反转整个字符串 "I am a student."-->".tneduts a ma I"
        reverseStr(chars,0,chars.length-1);

        //再把反转的单词  反转回来
        int l = 0, h = 0;
        while (h <= n) {
            if (h == n || chars[h] == ' ') {
                // j==n-1 到最后一个字母了
                // chars[j] == ' ' 是一个单词了
                // h-1 遇到空格 要反转空格前面的 所以最后一个字母的时候  需要越界
                // 例如abc是最后一个单词  需要让h回退到c上
                reverseStr(chars, l , h-1);
                l = h + 1;
            }
            h++;
        }
        return new String(chars);
    }

    /**
     * 反转函数
     * @param chars
     */
    private static void reverseStr(char[] chars, int l, int h) {
        while (l < h) {
            char c = chars[l];
            chars[l] = chars[h];
            chars[h] = c;
            l++;
            h--;
        }
    }

59、队列的最大值

/**
     * 通过维护大顶堆来完成
     * @param num
     * @param size
     * @return
     */
    public ArrayList<Integer> maxInWindowsHeap(int[] num, int size) {
        ArrayList<Integer> list = new ArrayList<>();
        if (size > num.length || size < 1) {
            return list;
        }
        //构建大顶堆大顶堆
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o2 - o1);
        for (int i=0; i<size; i++) {
            priorityQueue.add(num[i]);
        }
        //第一组的划窗的最大值
        list.add(priorityQueue.peek());

        //确保堆的大小为size
        for (int i=0, j=i+size; j<num.length; i++,j++) {
            //有新元素进入,先删除队列前面的值 因为其不在划窗范围内
            priorityQueue.remove(num[i]);
            //加入新进入划窗的元素,并且维持大顶堆
            priorityQueue.add(num[j]);
            list.add(priorityQueue.peek());
        }
        return list;
    }




    /**
     * 暴力搜索  O(nk)
     * @param num
     * @param size
     * @return
     */
    public static ArrayList<Integer> maxInWindowsSearch(int [] num, int size) {
        if (size == 0) {
            return new ArrayList<>();
        }
        ArrayList<Integer> list = new ArrayList<>();
        for (int i=0; i<num.length-size+1; i++) {
            int[] arr = new int[size];
            int index = 0;
            for (int j=i; j<size+i; j++) {
                arr[index] = num[j];
                index++;
            }
            list.add(getMax(arr));
        }
        return list;
    }

    private static int getMax(int[] arr) {
        int max = Integer.MIN_VALUE;
        for (int i=0; i<arr.length; i++) {
            max = max >= arr[i] ? max : arr[i];
        }
        return max;
    }

60、n个骰子的点数

	public List<Map<Integer, Double>> printProbability(int n) {
        final int face = 6;
        // 所有点数和
        final int pointNum = face * n;
        // 骰子数量 点数和
        long[][] dp = new long[n + 1][pointNum + 1];
        // 初始化 只有一个骰子时候的情况 i为点数  横坐标1个骰子(1,1)  纵坐标点数和(1,2)
        for (int i = 1; i <= face; i++) {
            dp[1][i] = 1;
        }

        //剩余的n-1个骰子
        for (int i = 2; i <= n; i++) {
            // j为点数和  使用i个骰子最小点数为i,每个骰子最小点是1
            for (int j = i; j <= pointNum; j++) {
                // 第i个骰子  点数为k->1-6
                for (int k = 1; k <= face && k <= j; k++) {
                    // 点数为j 本次点数k 1-6  那么
                    // 前面的点数和 j-1 k=1, j-2 k=2, j-3 k=3, j-4 k=4, j-5 k=5, j-6 k=6
                    // 如果本次点数k=3 那么前面是j-3时候 和为j
                    dp[i][j] += dp[i - 1][j - k];
                }
            }
        }

        // 每个骰子出现的点数6种 2个骰子的所有点数可能 6*6  3个 6*6*6
        final double totalNum = Math.pow(6, n);
        List<Map<Integer, Double>> ret = new ArrayList<>();
        for (int i = n; i <= pointNum; i++) {
            Map<Integer ,Double> map = new HashMap<>();
            map.put(i,dp[n][i] / totalNum);
            ret.add(map);
        }
        return ret;


  	// 当有3个骰子的时候  首先记录第一个  然后第二个  第三个进来时候,依赖第二个,
  	// 故第一个的记录没用了,可以清除 时间复杂度下降到O(n)
	public List<Map<Integer, Double>> printProbability2(int n) {
        final int face = 6;
        final int pointNum = face * n;
        long[][] dp = new long[2][pointNum + 1];

        // 初始化  只有一个骰子的时候
        for (int i = 1; i <= face; i++) {
            dp[0][i] = 1;
        }

        
      
        // 循环利用的标记  不需要记录所有 只需要在前一个的基础上继续操作即可
        int flag = 1;
        // 剩余的n-1个骰子
        for (int i = 2; i <= n; i++,flag = 1 - flag) {
            // 清除
            for (int j = 0; j <= pointNum; j++) {
                dp[flag][j] = 0;
            }
            for (int j = i; j <= pointNum; j++) {
                for (int k = 1; k <= face && k <= j; k++) {
                    // 清除之后 存入新的
                    dp[flag][j] += dp[1 - flag][j - k];
                }
            }
        }

        final double totalNum = Math.pow(6, n);
        List<Map<Integer, Double>> ret = new ArrayList<>();
        for (int i = n; i <= pointNum; i++) {
            Map<Integer, Double> map = new HashMap<>();
            map.put(i, dp[1-flag][i] / totalNum);
            ret.add(map);
        }

        return ret;
    }

61、扑克牌中的顺子

	public static boolean isContinuous(int [] numbers) {
        if(numbers.length != 5 || numbers == null) {
            return false;
        }
        Arrays.sort(numbers);
        // 统计0的个数 也就是大小王的个数  注意 这里的大小王不一定是2个,可能是5个
        int count0 = 0;
        for(int i=0; i<5; i++) {
            if(numbers[i] == 0) {
                count0++;
            }
        }
        // 统计距离顺子,相差多少 是否可以用王来弥补
        int countDitance = 0;
        for(int i=0; i<4; i++) {
            
            if(numbers[i] != 0) {
                // 有对子 不能成顺子  对子不是大小王
                if(numbers[i] == numbers[i+1]) {
                    return false;
                }
                int x = numbers[i+1] - numbers[i];
                countDitance += x > 1 ? x-1 : 0;
            }
        }
        return countDitance <= count0;
    }

62、圆圈中最后剩下的数字

	public int LastRemaining_Solution(int n, int m) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        for (int i=0; i<n; i++) {
            linkedList.add(i);
        }
        int i = 0;
        while (linkedList.size() > 1) {
            i = (i + m - 1) % linkedList.size();
            linkedList.remove(i);
        }
        return linkedList.size() == 1 ? linkedList.get(0) : -1;
    }

63、股票的最大利润

	public int maxDiff(int[] arr) {
        if(arr.length <= 1) {
            return 0;
        }
        int min = arr[0];
        int maxDiff = Integer.MIN_VALUE;
        for (int i=1, len=arr.length; i<len; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
            int t = arr[i] - min;
            maxDiff = Math.max(maxDiff, t);
        }
        return maxDiff;
    }

64、求 1+2+3+。。。+n

	public int Sum_Solution(int n) {
        int sum = n;
        // && 能够短路 故可以作为递归结束条件
        boolean flag = (n > 0) && ((sum += Sum_Solution( n - 1)) > 0);
        return sum;
    }

65、不用加减乘除做加法

	/**
     * 第一步:不考虑进位 1+1=0 0+0=0 0+1=1 1+0=1 异或可以得到这样的结果
     * 第二步:考虑进位   1+1=10 0+0=0 1+0=1 0+1=1 与运算,并左移一位
     * 第三步:前面两步的结果相加
     * 结束条件:不产生进位 那么说明第一步时候,就搞定了
     */
    public static int Add(int num1,int num2) {
        int sum, carry;
        while(num2 != 0){
            sum = (num1 ^ num2);
            carry = (num1 & num2) << 1;
            num1 = sum;
            num2 = carry;
        }
        return num1;
    }

66、构建乘积数组

//暴力破解
	public static int[] multiply1(int[] A) {
        int[] b = new int[A.length];
        //注意需要填充1,否则当前值为0,所有乘积都是0
        Arrays.fill(b,1);
        int index = 0;
        while(index < A.length) {
            for(int i=0; i<index; i++) {
                b[index] *= A[i];
            }
            for(int i=index+1; i<A.length; i++) {
                b[index] *= A[i];
            }
            index++;
        }
        return b;
    }
    
//大神的巧妙解法
    public static int[] multiply2(int[] A) {
        int n = A.length;
        int[] B = new int[n];
        // B[i] = A[0]*A[1]*A[2]*..*A[i-1]
        for (int i = 0, product = 1; i < n; product *= A[i], i++) {
            // product是前面数的乘积
            B[i] = product;
        }

        // product是后面A[i+1] ... A[n-1]的乘积
        for (int i = n - 1, product = 1; i >= 0; product *= A[i], i--) {
            // 再乘以前面的结果
            B[i] *= product;
        }
        return B;
    }

67、把字符串转换成整数

	public static int StrToInt(String str) {
        if (null == str || str.length() == 0) {
            return 0;
        }
        boolean isNegative = str.charAt(0) == '-';
        int num = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            // 第一位是符号 不做处理
            if (i == 0 && (c == '+' || c == '-')) {
                continue;
            }
            // 不合法
            if (c < '0' || c > '9') {
                return 0;
            }
            num = num * 10 + c - '0';
        }
        return isNegative ? -num : num;
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值