Object's Blog

算法刷题记录(第一周整合)

字数统计: 8.8k阅读时长: 38 min
2019/10/21 分享

前言

原先是一天一发,发现这样会有大量的篇幅,所以以后就将一周的算法题做一个整合。当然,记录还是每天来记录的,毕竟刚刷完题热腾腾的解题思路是必须得写下来的。

第一天题目汇总

第一题:二维数组中的查找

  • 题目描述

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

  • 解题思路

    从左下找,由于该数组有从左到右依次增大,从上到下依次增大的特点,所以左下的元素一定是该行最小的元素,却是该列最大的元素,所以如果target<该元素,则指针向上移,如果target>该元素,则指针向右移,如果相等,返回true。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class Solution {
    public boolean Find(int target, int [][] array) {
    int rowCount = array.length-1;
    int columnCount = 0;
    if(rowCount<0)
    return false;
    while(rowCount>=0&&columnCount<array[0].length) {
    if(target>array[rowCount][columnCount]) {
    columnCount++;
    }else if(target<array[rowCount][columnCount]) {
    rowCount--;
    }else {
    return true;
    }
    }
    return false;
    }
    }

第二题:替换空格

  • 题目描述

    请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

  • 解题思路

    ?????这个题????? 反正是可以调用jdk自带方法,也通过了。

  • 代码

    1
    2
    3
    public String replaceSpace(StringBuffer str) {
    return str.toString().replace(" ", "%20");
    }

第三题:从尾到头打印链表

  • 题目描述

    输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

  • 解题思路

    本来想着暴力求解,发现时间复杂度实在太大,其实这题可以用堆栈的思想,既然这个不是双向链表,只能正序遍历不能反序便利,但题目要求我们反向输出,那么就可以一次放入堆栈,先进后出,就完成了反序,ArrayList中有一个add(int index,T value)方法,可以在任意位置插入元素,所以可以一直往0号位置插入正在遍历的链表元素,最后返回的就是反向链表了。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    /**
    * public class ListNode {
    * int val;
    * ListNode next = null;
    *
    * ListNode(int val) {
    * this.val = val;
    * }
    * }
    *
    */
    import java.util.ArrayList;
    public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
    if(listNode==null) {
    return new ArrayList<Integer>();
    }
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    while(listNode!=null) {
    arrayList.add(0, listNode.val);
    listNode = listNode.next;
    }
    return arrayList;
    }
    }

第四题:重建二叉树

  • 题目描述

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

  • 解题思路

    1.确定先序遍历的第一个元素为根节点。

    2.在中序遍历序列中找到该元素的位置,该元素位置的左侧为该元素的左子树,右侧为该元素的右子树。

    3.为该元素的左右子树分别执行1、2两部操作。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    /**
    * Definition for binary tree
    * public class TreeNode {
    * int val;
    * TreeNode left;
    * TreeNode right;
    * TreeNode(int x) { val = x; }
    * }
    */
    import java.util.Arrays;
    public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
    if(pre.length<=0||in.length<=0)
    return null;
    if(pre.length==1||in.length==1)
    return new TreeNode(pre[0]);
    TreeNode root = new TreeNode(pre[0]);
    for(int i=0;i<in.length;i++) {
    if(root.val == in[i]) {
    root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1),Arrays.copyOfRange(in, 0, i));
    root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i+1,pre.length), Arrays.copyOfRange(in, i+1,in.length));
    break;
    }
    }
    return root;
    }
    }

第五题:用两个栈实现队列

  • 题目描述

    用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

  • 解题思路

    栈的特点是先入后出,队列的特点是先入先出,所以要用两个栈来实现队列,还是比较简单的,只需要将一个栈的元素重新pop,然后push到另一个栈中,再pop,就可以得到队列的结果。

    根据该思路,可以设计如下步骤:

    1.push时,就正常push到stack1中

    2.pop时,如果stack2中有元素则直接pop,如果stack2中没有元素,则将stack1中的所有元素pop,然后push进stack2中,然后将stack2栈顶元素pop。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import java.util.Stack;

    public class Solution {
    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.size() <= 0) {
    while (stack1.size() > 0) {
    int i = stack1.pop();
    stack2.push(i);
    }
    }
    return stack2.pop();
    }
    }

第二天题目汇总

第一题:旋转数组的最小数字

  • 题目描述

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
    例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
    NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

  • 解题思路

    刚开始没看懂题意,这不就是找最小值吗,嗯真的是找最小值。剑指Offer刚开始题目的难度真的很适合入门者练习。。。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import java.util.ArrayList;
    import java.util.Arrays;
    public class Solution {
    public int minNumberInRotateArray(int [] array) {
    if(array.length==0)
    return 0;
    Arrays.sort(array);
    return array[0];
    }
    }

第二题:斐波那契数列

  • 题目描述

    大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。

    n<=39

  • 解题思路

    斐波那契数列:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)

    SO。。。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Solution {
    public int Fibonacci(int n) {
    if(n==0)
    return 0;
    if(n==1)
    return 1;
    return Fibonacci(n-1)+Fibonacci(n-2);
    }
    }

第三题:跳台阶

  • 题目描述

    一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

  • 解题思路

    另一种形式的斐波那契数列。

    首先:

    跳一级台阶的跳法为1(只能跳1阶)

    跳两级台阶的方法为2(跳1阶两次,跳2阶1次)

    跳三级台阶的方法为3(跳1阶三次,跳1阶一次跳2阶一次,跳2阶一次跳1阶一次)

    跳四级台阶的方法为5(1111、211、121、112、22)

    ……

    所以:

    跳n阶台阶的方法数量等于,跳n-1次的方法数量+跳n-2次的方法数量

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    public class Solution {
    public int JumpFloor(int target) {
    if(target==1) return 1;
    if(target==2) return 2;
    if(target==3) return 3;
    return JumpFloor(target-1)+JumpFloor(target-2);
    }
    }

第四题:变态跳台阶

  • 题目描述

    一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

  • 解题思路

    首先先抓住不变的,跳一级一定只有一种跳法,跳两级一定只有两种跳法。

    那么跳3级呢?

    1+1+1,1+2,2+1,3,一共有四种跳法。

    跳三级可以分解为跳两级的所有跳法+跳两级的所有跳法+加上一次跳3级的一种跳法。所以是1+2+1=4种跳法。

    那么跳4级呢?

    1+1+1+1,2+1+1,1+2+1,1+1+2,2+2,3+1,1+3,4。一共八种跳法。

    跳四级可以分解为,跳一级的所有跳法(1)+跳两级的所有跳法(2)+跳三级的所有跳法(4)+一次性跳4级的所有跳法(1)。

    所以,跳n级的跳法就等于:本身一次性跳n级的1种跳法,加上跳n-1级的所有跳法,加上跳n-2级的所有跳法…….

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class Solution {
    public int JumpFloorII(int target) {
    if(target==1)
    return 1;
    else if(target==2)
    return 2;
    else{
    //关键
    int count = 1;
    while(target>1){
    count+=JumpFloorII(target-1);
    target-=1;
    }
    return count;
    }
    }
    }

第五题:矩形覆盖

  • 题目描述

    我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2 * 1的小矩形无重叠地覆盖一个2 * n的大矩形,总共有多少种方法?

  • 解题思路

    还是斐波那契数列,和第三题很相似。

    首先,

    用1个2 * 1的小矩形覆盖一个2 * 1的大矩形 只有一种方法。

    用2个2 * 1的小矩形覆盖一个2 * 2的大矩形 只有两种方法。

    用3个2 * 1的小矩形覆盖一个2 * 3的大矩形 只有三种方法。

    覆盖2 * 3 的大矩形,可以分解为,一个2 * 1的大矩形和一个2 * 2的大矩形。而这两个,一个方法是1种,一个方法是2种.

    那么大概可以知道,覆盖一个2 * n的大矩形,可以分解为,覆盖一个2 * n-1的大矩形和覆盖一个2 * n-2的大矩形的所有方法相加。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Solution {
    public int RectCover(int target) {
    if(target==0) return 0;
    else if(target==1) return 1;
    else if(target==2) return 2;
    else if(target==3) return 3;
    return RectCover(target-1)+RectCover(target-2);
    }
    }

第三天题目汇总

第一题:二进制中1的个数

  • 题目描述

    输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

  • 解题思路

    将传入的参数右移,每次判断最后一位是否为1,如果为1count++即可。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Solution {
    public int NumberOf1(int n) {
    int count = 0;
    while(n!=0){
    count+=n&1;//判断最后一位是否为1 1=000000...001 &运算只能判断最后一位
    n = n>>>1;
    }
    return count;
    }
    }

第二题:数值的整数次方

  • 题目描述

    给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
    保证base和exponent不同时为0

  • 解题思路

    循环解,需要注意的是 exponent有可能小于0

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Solution {
    public double Power(double base, int exponent) {
    double result = 1;
    boolean isNegative = false;
    if(exponent<0){
    exponent *= -1;
    isNegative = true;
    }
    for(int i = 0;i < exponent;i++){
    result *= base;
    }
    if(isNegative)
    result = 1/result;
    return result;
    }
    }

第三题:调整数组顺序使奇数位于偶数前面

  • 题目描述

    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

  • 解题思路

    开辟两个辅助数组,分别存奇数和偶数,最后按顺序回写到array中

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import java.util.ArrayList;
    import java.util.List;
    public class Solution {
    public void reOrderArray(int [] array) {
    List<Integer> odd= new ArrayList<>();
    List<Integer> even = new ArrayList<>();

    for(int i=0;i<array.length;i++) {
    if(array[i]%2!=0)
    odd.add(array[i]);
    else
    even.add(array[i]);
    }
    int count = 0;
    for(Integer i:odd) {
    array[count] = i;
    count++;
    }
    for(Integer i :even) {
    array[count] = i;
    count++;
    }
    for(int i=0;i<array.length;i++) {
    System.out.println(array[i]);
    }
    }
    }

第四题:链表中倒数第k个结点

  • 题目描述

    输入一个链表,输出该链表中倒数第k个结点。

  • 解题思路

    和前几天做的链表逆序输出想法相同,用栈的思想。先把数组入栈,然后pop出倒数第n个数。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    /*
    public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
    this.val = val;
    }
    }*/
    import java.util.Stack;
    public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
    if(head == null) return null;
    Stack<ListNode> nodeStack = new Stack<ListNode>();
    ListNode pointer = head;
    while(pointer!=null) {
    nodeStack.push(pointer);
    pointer = pointer.next;
    }
    for(int i = 0;i<k;i++) {
    if(nodeStack.size()==0) return null;
    pointer = nodeStack.pop();
    }
    return pointer;
    }
    }

第五题:反转链表

  • 题目描述

    输入一个链表,反转链表后,输出新链表的表头。

  • 解题思路

    依旧用栈的思想来反转链表,然后构建新链表输出表头。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public ListNode ReverseList(ListNode head) {
    ListNode pointer = head;
    Stack<Integer> nodeStack = new Stack<Integer>();
    while(pointer!=null) {
    nodeStack.push(pointer.val);
    pointer = pointer.next;
    }
    pointer = head;
    while(!nodeStack.empty()) {
    pointer.val = nodeStack.pop();
    System.out.println(pointer.val);
    pointer = pointer.next;
    }
    return head;
    }

第四天题目汇总

第一题:

  • 题目描述

    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

  • 解题思路

    新建一个新链表,命名为mergeList,对两个已有链表分别遍历,将节点值小的加入新链表。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public ListNode Merge(ListNode list1,ListNode list2) {
    if(list1==null) return list2;
    if(list2==null) return list1;
    ListNode cur = null;
    ListNode mergeList = null;
    while(list1!=null&&list2!=null) {
    if(list1.val<=list2.val) {
    if(mergeList==null) mergeList = cur = list1;
    else {
    cur.next = list1;
    cur = cur.next;
    }
    list1 = list1.next;
    }else {
    if(mergeList==null) mergeList = cur = list2;
    else {
    cur.next = list2;
    cur = cur.next;
    }
    list2 = list2.next;
    }
    }
    if(list1!=null) cur.next = list1;
    if(list2!=null) cur.next = list2;
    return mergeList;
    }

第二题:树的子结构

  • 题目描述

    输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

  • 解题思路

    1.判断A和B是否为空,如果有一个为空直接返回false。

    2.进入isSubTree判断B是否为null,如果B为null则返回true。

    3.判断A是否为null,如果A为null则返回false。

    4.判断根节点是否和B一致,如果不一致则判断A的左子树和B是否一致,如果不一致则继续找下一个左子树,如果一致则对左右子树进行比对。如果A为null则直接返回false

    5.判断右子树的方式和4相同

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
    if(root1==null||root2==null) return false;
    return isSubtree(root1,root2)||HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
    }
    public boolean isSubtree(TreeNode root1,TreeNode root2) {
    if(root2==null) return true;
    if(root1==null) return false;
    if(root1.val!=root2.val) return false;

    return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
    }

第三题:二叉树的镜像

  • 题目描述

    操作给定的二叉树,将其变换为源二叉树的镜像。

  • 解题思路

    如果给的树为空,则直接返回。

    如果给的子树左子树或者右子树不为空则交换左右子树。

    对完成操作的左右子树分别再做交换操作。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Solution {
    public void Mirror(TreeNode root) {
    change(root);
    }
    public void change(TreeNode root){
    if(root==null) return;
    if(root.left!=null||root.right!=null){
    TreeNode temp = root.left;
    root.left = root.right;
    root.right = temp;
    }
    change(root.left);
    change(root.right);
    }
    }

第四题:顺时针打印矩阵

  • 题目描述

    输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

  • 解题思路

    画了个图,可以将矩阵分为左侧,右侧,上侧,下侧,这四个边界,分别用left,right,top,buttom标识。

    程序从左上开始向右遍历,当遍历到right边界时,表示第一行遍历结束,那么这一行之后就不会再遍历到了。所以将上边界下移一行,再开始遍历右边界,当遍历到buttom时表示右边界遍历结束。那么将right向左移一列。以这个思想,一直遍历下去。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public ArrayList<Integer> printMatrix(int[][] matrix) {
    int left = 0;
    int top = 0;
    int right = matrix[0].length - 1;
    int buttom = matrix.length - 1;
    ArrayList<Integer> res = new ArrayList<>();
    while (true) {
    for (int i = left; i <= right; i++)
    res.add(matrix[top][i]);
    top++;
    if (top > buttom)
    break;
    for (int i = top; i <= buttom; i++)
    res.add(matrix[i][right]);
    right--;
    if (right < left)
    break;
    for (int i = right; i >= left; i--)
    res.add(matrix[buttom][i]);
    buttom--;
    if (buttom < top)
    break;
    for (int i = buttom; i >= top; i--)
    res.add(matrix[i][left]);
    left++;
    if (left > right)
    break;
    }
    return res;
    }

第五题:包含min()函数的栈

  • 题目描述:

    定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

  • 解题思路:

    因为要自己定义栈的数据结构,所以我第一次在栈中定义了一个min属性来在push时记录最小元素,然后min方法只需要把min返回就可以了,但是我发现我把问题想简单了,因为如果最小值被pop,栈中元素并不会被min记录。所以我用了另一种方法,用两个堆栈,一个堆栈放正常数据,另一个堆栈放最小值,当每次入栈被判定为最小值的那个属性,再入这个最小值栈,每次出栈被判定为最小值的那个属性,被最小值栈pop,min属性刷新为最小值栈的栈顶属性值。

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class Solution {
    Stack<Integer> stack = new Stack<Integer>();
    Stack<Integer> minStack = new Stack<Integer>();
    int min = Integer.MAX_VALUE;
    public void push(int node) {
    stack.push(node);
    if(node<=this.min) {
    min = node;
    minStack.push(node);
    }
    }

    public void pop() {
    if(stack!=null&&!stack.empty()) {
    int num = stack.pop();
    if(num==min) {
    minStack.pop();
    min = minStack.peek();
    }
    }
    }

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

    public int min() {
    return min;
    }
    }

笔试题:买橙子

  • 题目描述:

    小明去附近的水果店买橙子,水果商贩只提供整袋购买,有每袋6个和每袋8个的包装(包装不可拆分)。

    可是小明只想购买恰好n个橙子,并且尽量少的袋数方便携带。如果不能购买恰好n个橙子,小明将不会购买。

    输入:一个整数n,表示小明想要买n个橙子。

    输出:最少购买的袋数,如果不能恰好买n个橙子,则返回-1。

    示例:

    输入:20

    返回:3

  • 解题思路:

    这是我今天除了做练习题以外的一道真实笔试题,记录下来。

    首先,先买最多的。

    也就是先尽量买每袋8个的包装。

    如果橙子不够,则买每袋6个的包装。

    如果没法恰好买n个,那么就先试试把每袋8个的换成每袋6个的。直到每袋8个为0还是没法恰好买n个,则返回0。如果这个过程中橙子的数量恰好为n个,则这就是最少购买的袋数。

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Solution {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    for(int i=n/8;i>=0;i--) {
    if((n-i*8)%6==0) {
    System.out.println(i+(n-i*8)/6);
    return;
    }
    }
    System.out.println(-1);
    }
    }

第五天题目汇总

第一题: 栈的压入、弹出序列

  • 题目描述

    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

  • 解题思路

    创建一个新栈stack,将pushA中的元素压栈,每次压栈时判断popA中的第一个元素是否与栈顶元素相等,如果相等直接出栈,如果不相等继续压栈,循环往复,最后如果循环结束stack为空,表示可以正常弹出,否则返回false。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public boolean IsPopOrder(int [] pushA,int [] popA) {
    Stack<Integer> stack = new Stack<Integer>();
    int num = 0;
    for(int i=0;i<pushA.length;i++) {
    stack.push(pushA[i]);
    while(!stack.empty()&&popA[num]==stack.peek()){
    stack.pop();
    num++;
    }
    }
    if(stack.empty()) return true;
    else return false;
    }

第二题: 从上往下打印二叉树

  • 题目描述

    从上往下打印出二叉树的每个节点,同层节点从左至右打印。 
  • 解题思路

    层次遍历,借助队列,每次分别存入root,root.left,root.right。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<Integer>();
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    if(root==null) return list;
    queue.offer(root);
    while(!queue.isEmpty()) {
    TreeNode t = queue.poll();
    if(t.left!=null) queue.offer(t.left);
    if(t.right!=null) queue.offer(t.right);
    list.add(t.val);
    }
    return list;
    }

第三题: 二叉搜索树的后序遍历序列

  • 题目描述

    输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

  • 解题思路

    这道题比较难,想了很久也不知道怎么做。最后参考了网上的大佬。

    思想大概是这样的:

    假设有这么一个序列, [3, 4, 9, 5, 12, 11, 10] 。

    根据后序遍历,可以得知,最后一个数一定是根节点。所以root等于10,又因为是二叉搜索树,那么根节点左边的节点一定小于根节点,右边的一定大于根节点。

    那么问题就变为如何找到根节点的左右孩子上。

    遍历数组,左孩子一定不可能大于根节点,那么第一个大于根节点的就是右孩子,上一个就是左孩子。

    找到左右孩子后,可以判断左右孩子的分支是否符合要求,如果右孩子中的元素比根节点小,那么直接返回false。由于第一次遍历已经确定左孩子左边均小于根节点,所以无需重复判断。

    然后再对左右孩子分别进行这样的过程。

    递归得出结果。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
    if(sequence.length<=0)
    return false;
    int mid=0;
    int length = sequence.length-1;
    while(mid<length)
    if(sequence[mid++]>sequence[length]) break;
    int after = mid;
    while(after<length) {
    if(sequence[after++]<sequence[length]) return false;
    }
    boolean left = true,right = true;
    if(mid>0) left = VerifySquenceOfBST(Arrays.copyOfRange(sequence, 0, mid));
    if(mid<length) right = VerifySquenceOfBST(Arrays.copyOfRange(sequence, mid, length));
    return left&&right;
    }
    }

第四题: 二叉树中和为某一值的路径

  • 题目描述

    输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

  • 解题思路

    从根节点出发,将target减去路径中遇到的数,如果target等于0,且到了叶节点,在最终结果集中加入路径。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Solution {
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    ArrayList<Integer> list = new ArrayList<Integer>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
    if(root==null) return res;
    target -= root.val;
    list.add(root.val);
    if(target==0&&root.left==null&&root.right==null) res.add(new ArrayList<Integer>(list));
    FindPath(root.left,target);
    FindPath(root.right,target);
    /*去掉最后一个,相当于返回父节点,然后去查找另外一条路径*/
    list.remove(list.size()-1);
    return res;
    }
    }

第五题: 复杂链表的复制

  • 题目描述

    输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

  • 解题思路

    题意是不能直接引用参数中的节点,那么我们直接创建新节点然后把值赋值过来即可。

    这里要注意的是,要判断random节点是否为空,不然产生空指针异常。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
    if(pHead==null)
    return null;
    RandomListNode head = new RandomListNode(pHead.label);
    RandomListNode pointer = head;
    while(pHead.next!=null) {
    RandomListNode nextNode = new RandomListNode(pHead.next.label);
    RandomListNode randomNode = null;
    if(pHead.random!=null)
    randomNode = new RandomListNode(pHead.random.label);
    pointer.next = nextNode;
    pointer.random = randomNode;
    pointer = pointer.next;
    pHead = pHead.next;
    }
    return head;
    }
    }

第六天题目汇总

第一题: 二叉搜索树与双向链表

  • 题目描述

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

  • 解题思路

    很简单的一道题,首先二叉搜索树中序遍历可以得到有序集合。所以先中序遍历,并将集合存入List。

    遍历结束后将list中的TreeNode左右子树分别指向前一个节点和后一个节点,就形成了双向链表。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import java.util.List;
    import java.util.ArrayList;
    public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
    if(pRootOfTree==null) return null;
    List<TreeNode> list = new ArrayList<TreeNode>();
    mid(pRootOfTree,list);
    for(int i=0;i<list.size()-1;i++) {
    if(list.get(i+1)!=null){
    list.get(i).right = list.get(i+1);
    list.get(i+1).left = list.get(i);
    }
    }
    return list.get(0);
    }

    public void mid(TreeNode root,List<TreeNode> list) {
    if(root.left!=null) mid(root.left,list);
    list.add(root);
    if(root.right!=null) mid(root.right,list);
    }
    }

第二题: 字符串的排列

  • 题目描述

    输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

  • 解题思路

    假设 字符串为 abc 则它的所有排列方式等于 a+func(b,c)+b+func(a,c)+c+func(b,a)+b+func(c)+c+func(b)+func(c)

    func可以得到所有序列

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import java.util.ArrayList;
    import java.util.Arrays;
    public class Solution {
    public ArrayList<String> Permutation(String str) {
    ArrayList<String> res = new ArrayList<String>();
    StringBuilder strBuilder = new StringBuilder(str);
    if(str.length()==1) res.add(str);
    else {
    for(int i=0;i<strBuilder.length();i++) {
    if(i==0||strBuilder.charAt(0)!=strBuilder.charAt(i)) {
    char temp = strBuilder.charAt(i);
    strBuilder.setCharAt(i, strBuilder.charAt(0));
    strBuilder.setCharAt(0, temp);
    ArrayList<String> tempRes = Permutation(strBuilder.substring(1));
    for(int j = 0;j<tempRes.size();j++) {
    res.add(strBuilder.substring(0,1)+tempRes.get(j));
    }
    temp = strBuilder.charAt(0);
    strBuilder.setCharAt(0, strBuilder.charAt(i));
    strBuilder.setCharAt(i, temp);
    }
    }
    //冒泡
    for(int i=0;i<res.size();i++) {
    for(int j=0;j<res.size()-i-1;j++) {
    if(res.get(j).compareTo(res.get(j+1))>0) {
    String temp = res.get(j);
    res.set(j, res.get(j+1));
    res.set(j+1, temp);
    }
    }
    }
    }

    return res;
    }
    }

第三题:数组中出现次数超过一半的数字

  • 题目描述

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

  • 解题思路

    先排序,保证每个数连续出现,然后计数。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import java.util.Arrays;
    public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
    if(array.length==1)
    return array[0];
    int mid = array.length/2;
    Arrays.sort(array);
    int count = 0;
    int res;
    for(int i = 1;i<array.length;i++) {
    if(array[i]==array[i-1]) {
    count++;
    res = array[i];
    if(count>=mid)
    return res;
    }else {
    count=0;
    }
    }
    return 0;
    }
    }

第四题: 最小的K个数

  • 题目描述

    输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

  • 解题思路

    排序,遍历前k个

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import java.util.Arrays;
    import java.util.ArrayList;
    public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    if(k>input.length)
    return arrayList;
    Arrays.sort(input);
    for(int i=0;i<k;i++){
    arrayList.add(input[i]);
    }
    return arrayList;
    }
    }

第五题: 连续子数组的最大和

  • 题目描述

    HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

  • 解题思路

    动态规划, 最大子数组的和一定是由当前元素和之前最大连续子数组的和叠加在一起形成的 ,如果当前最大数组和大于前一个元素,那么一定是递增的。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
    int[] dp = new int[array.length];
    int max = array[0];
    dp[0] = array[0];
    for(int i=1;i<array.length;i++) {
    int newMax = array[i]+dp[i-1];
    if(array[i]<newMax) dp[i]=newMax;
    else dp[i]=array[i];
    if(dp[i]>max) max = dp[i];
    }
    return max;
    }

    }

第七天题目汇总

第一题: 整数中1出现的次数(从1到n整数中1出现的次数)

  • 题目描述

    求出1到13的整数中1出现的次数,并算出100到1300的整数中1出现的次数?为此他特别数了一下1到13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

  • 解题思路

    将数字转换成字符串,然后遍历字符串中的每个字符,如果是1就直接让计数器+1,最后返回计数器的值。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
    if(n<1) return 0;
    if(n==1) return 1;
    int res = 0;
    String str = new String();
    for(int i=0;i<=n;i++) {
    str = String.valueOf(i);
    for(int j=0;j<str.length();j++) {
    if('1'==str.charAt(j))
    res++;
    }
    }
    return res;
    }
    }

第二题: 把数组排成最小的数

  • 题目描述

    输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

  • 解题思路

    将数字转为String进行正反拼接,然后转为Long(必须为Long,不然会有过大的情况),进行比较,通过冒泡,找到最小的排列方式。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class Solution {
    public String PrintMinNumber(int [] numbers) {
    String res = new String();
    //冒泡
    for(int i=0;i<numbers.length;i++) {
    for(int j=0;j<numbers.length-i-1;j++) {
    String str = String.valueOf(numbers[j])+String.valueOf(numbers[j+1]);
    String rts = String.valueOf(numbers[j+1])+String.valueOf(numbers[j]);
    if(Long.valueOf(str)>Long.valueOf(rts)) {
    int temp = numbers[j];
    numbers[j] = numbers[j+1];
    numbers[j+1] = temp;
    }
    }
    }
    for(int i=0;i<numbers.length;i++) {
    res+=String.valueOf(numbers[i]);
    }
    return res;
    }
    }

第三题:丑数

  • 题目描述

    把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

  • 解题思路

    如果一个数小于7,那么一定是丑数。

    如果大于等于7,则经过以下逻辑:将数组中的元素分别乘2,乘3,乘5,分不到3个数组(这里用三个指针表示),然后找到三个数组中最小的元素,加入丑数数组,最后返回索引指向的那个数。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Solution {
    public int GetUglyNumber_Solution(int index) {
    if(index<7) return index;
    List<Integer> res = new ArrayList<Integer>();
    res.add(0, 1);
    int t2 = 0,t3=0,t5=0;
    for(int i=1;i<index;++i) {
    res.add(Math.min(res.get(t2)*2,Math.min(res.get(t3)*3, res.get(t5)*5)));
    if(res.get(i)==res.get(t2)*2) t2++;
    if(res.get(i)==res.get(t3)*3) t3++;
    if(res.get(i)==res.get(t5)*5) t5++;
    }
    return res.get(index-1);
    }
    }

第四题:第一个只出现一次的字符

  • 题目描述

    在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).

  • 解题思路

    借助Map和List

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public int FirstNotRepeatingChar(String str) {
    char[] ch = str.toCharArray();
    Map<String,Integer> map = new LinkedHashMap<String,Integer>();
    ArrayList<String> list = new ArrayList<String>();
    for(int i=0;i<ch.length;i++) {
    map.put(String.valueOf(ch[i]), 0);
    list.add(String.valueOf(ch[i]));
    }
    for(int i=0;i<ch.length;i++) {
    int value = map.get(String.valueOf(ch[i]));
    map.put(String.valueOf(ch[i]),value+1);
    }
    for(String key : map.keySet()) {
    if(map.get(key)==1)
    return list.indexOf(key);
    }
    return -1;
    }

第五题: 数组中的逆序对

  • 题目描述

    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

    输入描述:

    题目保证输入的数组中没有的相同的数字数据范围:

    对于%50的数据,size<=10^4

    对于%75的数据,size<=10^5

    对于%100的数据,size<=2*10^5

  • 解题思路

    暂时不明白。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    public class Solution {
    public int InversePairs(int [] array) {
    if(array==null||array.length==0)
    {
    return 0;
    }
    int[] copy = new int[array.length];
    for(int i=0;i<array.length;i++)
    {
    copy[i] = array[i];
    }
    int count = InversePairsCore(array,copy,0,array.length-1);//数值过大求余
    return count;

    }
    private int InversePairsCore(int[] array,int[] copy,int low,int high)
    {
    if(low==high)
    {
    return 0;
    }
    int mid = (low+high)>>1;
    int leftCount = InversePairsCore(array,copy,low,mid)%1000000007;
    int rightCount = InversePairsCore(array,copy,mid+1,high)%1000000007;
    int count = 0;
    int i=mid;
    int j=high;
    int locCopy = high;
    while(i>=low&&j>mid)
    {
    if(array[i]>array[j])
    {
    count += j-mid;
    copy[locCopy--] = array[i--];
    if(count>=1000000007)//数值过大求余
    {
    count%=1000000007;
    }
    }
    else
    {
    copy[locCopy--] = array[j--];
    }
    }
    for(;i>=low;i--)
    {
    copy[locCopy--]=array[i];
    }
    for(;j>mid;j--)
    {
    copy[locCopy--]=array[j];
    }
    for(int s=low;s<=high;s++)
    {
    array[s] = copy[s];
    }
    return (leftCount+rightCount+count)%1000000007;
    }
    }

原文作者:Object

原文链接:http://blog.objectspace.cn/2019/10/21/算法刷题记录(第一周整合)/

发表日期:2019 October 21st, 1:03:15 pm

更新日期:2019 October 21st, 1:07:14 pm

版权声明:未经作者授权请勿转载

目录
  1. 1. 前言
  2. 2. 第一天题目汇总
    1. 2.1. 第一题:二维数组中的查找
      1. 2.1.1. 题目描述
      2. 2.1.2. 解题思路
      3. 2.1.3. 代码
    2. 2.2. 第二题:替换空格
      1. 2.2.1. 题目描述
      2. 2.2.2. 解题思路
      3. 2.2.3. 代码
    3. 2.3. 第三题:从尾到头打印链表
      1. 2.3.1. 题目描述
      2. 2.3.2. 解题思路
      3. 2.3.3. 代码
    4. 2.4. 第四题:重建二叉树
      1. 2.4.1. 题目描述
      2. 2.4.2. 解题思路
      3. 2.4.3. 代码
    5. 2.5. 第五题:用两个栈实现队列
      1. 2.5.1. 题目描述
      2. 2.5.2. 解题思路
      3. 2.5.3. 代码
  3. 3. 第二天题目汇总
    1. 3.1. 第一题:旋转数组的最小数字
      1. 3.1.1. 题目描述
      2. 3.1.2. 解题思路
      3. 3.1.3. 代码
    2. 3.2. 第二题:斐波那契数列
      1. 3.2.1. 题目描述
      2. 3.2.2. 解题思路
      3. 3.2.3. 代码
    3. 3.3. 第三题:跳台阶
      1. 3.3.1. 题目描述
      2. 3.3.2. 解题思路
      3. 3.3.3. 代码
    4. 3.4. 第四题:变态跳台阶
      1. 3.4.1. 题目描述
      2. 3.4.2. 解题思路
      3. 3.4.3. 代码
    5. 3.5. 第五题:矩形覆盖
      1. 3.5.1. 题目描述
      2. 3.5.2. 解题思路
      3. 3.5.3. 代码
  4. 4. 第三天题目汇总
    1. 4.1. 第一题:二进制中1的个数
      1. 4.1.1. 题目描述
      2. 4.1.2. 解题思路
      3. 4.1.3. 代码
    2. 4.2. 第二题:数值的整数次方
      1. 4.2.1. 题目描述
      2. 4.2.2. 解题思路
      3. 4.2.3. 代码
    3. 4.3. 第三题:调整数组顺序使奇数位于偶数前面
      1. 4.3.1. 题目描述
      2. 4.3.2. 解题思路
      3. 4.3.3. 代码
    4. 4.4. 第四题:链表中倒数第k个结点
      1. 4.4.1. 题目描述
      2. 4.4.2. 解题思路
      3. 4.4.3. 代码
    5. 4.5. 第五题:反转链表
      1. 4.5.1. 题目描述
      2. 4.5.2. 解题思路
      3. 4.5.3. 代码
  5. 5. 第四天题目汇总
    1. 5.1. 第一题:
      1. 5.1.1. 题目描述
      2. 5.1.2. 解题思路
      3. 5.1.3. 代码
    2. 5.2. 第二题:树的子结构
      1. 5.2.1. 题目描述
      2. 5.2.2. 解题思路
      3. 5.2.3. 代码
    3. 5.3. 第三题:二叉树的镜像
      1. 5.3.1. 题目描述
      2. 5.3.2. 解题思路
      3. 5.3.3. 代码
    4. 5.4. 第四题:顺时针打印矩阵
      1. 5.4.1. 题目描述
      2. 5.4.2. 解题思路
      3. 5.4.3. 代码
    5. 5.5. 第五题:包含min()函数的栈
      1. 5.5.1. 题目描述:
      2. 5.5.2. 解题思路:
      3. 5.5.3. 代码:
    6. 5.6. 笔试题:买橙子
      1. 5.6.1. 题目描述:
      2. 5.6.2. 解题思路:
      3. 5.6.3. 代码:
  6. 6. 第五天题目汇总
    1. 6.1. 第一题: 栈的压入、弹出序列
      1. 6.1.1. 题目描述
      2. 6.1.2. 解题思路
      3. 6.1.3. 代码
    2. 6.2. 第二题: 从上往下打印二叉树
      1. 6.2.1. 题目描述
      2. 6.2.2. 解题思路
      3. 6.2.3. 代码
    3. 6.3. 第三题: 二叉搜索树的后序遍历序列
      1. 6.3.1. 题目描述
      2. 6.3.2. 解题思路
      3. 6.3.3. 代码
    4. 6.4. 第四题: 二叉树中和为某一值的路径
      1. 6.4.1. 题目描述
      2. 6.4.2. 解题思路
      3. 6.4.3. 代码
    5. 6.5. 第五题: 复杂链表的复制
      1. 6.5.1. 题目描述
      2. 6.5.2. 解题思路
      3. 6.5.3. 代码
  7. 7. 第六天题目汇总
    1. 7.1. 第一题: 二叉搜索树与双向链表
      1. 7.1.1. 题目描述
      2. 7.1.2. 解题思路
      3. 7.1.3. 代码
    2. 7.2. 第二题: 字符串的排列
      1. 7.2.1. 题目描述
      2. 7.2.2. 解题思路
      3. 7.2.3. 代码
    3. 7.3. 第三题:数组中出现次数超过一半的数字
      1. 7.3.1. 题目描述
      2. 7.3.2. 解题思路
      3. 7.3.3. 代码
    4. 7.4. 第四题: 最小的K个数
      1. 7.4.1. 题目描述
      2. 7.4.2. 解题思路
      3. 7.4.3. 代码
    5. 7.5. 第五题: 连续子数组的最大和
      1. 7.5.1. 题目描述
      2. 7.5.2. 解题思路
      3. 7.5.3. 代码
  8. 8. 第七天题目汇总
    1. 8.1. 第一题: 整数中1出现的次数(从1到n整数中1出现的次数)
      1. 8.1.1. 题目描述
      2. 8.1.2. 解题思路
      3. 8.1.3. 代码
    2. 8.2. 第二题: 把数组排成最小的数
      1. 8.2.1. 题目描述
      2. 8.2.2. 解题思路
      3. 8.2.3. 代码
    3. 8.3. 第三题:丑数
      1. 8.3.1. 题目描述
      2. 8.3.2. 解题思路
      3. 8.3.3. 代码
    4. 8.4. 第四题:第一个只出现一次的字符
      1. 8.4.1. 题目描述
      2. 8.4.2. 解题思路
      3. 8.4.3. 代码
    5. 8.5. 第五题: 数组中的逆序对
      1. 8.5.1. 题目描述
      2. 8.5.2. 解题思路
      3. 8.5.3. 代码