LeetCode基础算法50题Day02

目录

1、计算力扣银行的钱

2、排序数组

(1)、冒泡排序

(2)、选择排序

(3)、插入排序

(4)、快速排序


1、计算力扣银行的钱

        Hercy想要为购买第一辆车存钱。他每天都往力扣银行里存钱。最开始,他在周一的时候存入 1 块钱。从周二到周日,他每天都比前一天多存入 1 块钱。在接下来每一个周一,他都会比 前一个周一 多存入1块钱。给你n,请你返回在第 n 天结束的时候他在力扣银行总共存了多少块钱。

思路:根据以下我自己的分析,发现有规律可以使用,比如两周之间的总存钱数,每周内天与天之间的差额等等。

LeetCode基础算法50题Day02_第1张图片

上代码:

class Solution {
    public int totalMoney(int n) {
        int weeks = n/7;  //完整周的个数
        int days = n%7;   //不完整周里的天数
        int mondayMoney = weeks+1; //不完整周里的周一的存钱数量
        int firstWeekMoney = 28; //第一个完整周的总存钱数
        int daysMoney = 0; //不完整周里所有天数的存钱数
        int fullWeeksMoney; //所有完整周的总存钱数
        if (weeks==0){
            fullWeeksMoney=0;
        }else {
            fullWeeksMoney=28;
            for (int i = 1; i < weeks; i++) {
                firstWeekMoney += 7;  //每一个完整周都比前一周多存7块钱
                fullWeeksMoney += firstWeekMoney;
            }
        }
        if (days >= 1){
            daysMoney = mondayMoney;
            for (int i = 1; i < days; i++) {
                mondayMoney += 1; //每一天都比前一天多存1块钱
                daysMoney += mondayMoney;
            }
        }

        return fullWeeksMoney+daysMoney;
    }
}

 上述代码是直接按照周和天的不同情况进行讨论和运算的。没有采用任何公式。提交运行的结果后,发现内存占用过高。

LeetCode基础算法50题Day02_第2张图片

 利用公式的代码如下:

class Solution {
    public int totalMoney(int n) {
        int week = n/7;
        int day = n%7;
        // 完整周
        int firstWeekMoney = (1+7)*7/2; // 第一个完整周存钱数
        int lastWeekMoney = firstWeekMoney + 7*(week-1); // 最后一个完整周存钱数 (等差数列公式)
        int weeksMoney = (firstWeekMoney + lastWeekMoney) * week / 2; // 完整周总存钱数 (等差数列求和)
        // 非完整周
        int firstDayMoney = 1 + week; // 非完整周第一天存钱数
        int lastDayMoney = firstDayMoney + 1*(day-1); // 非完整周最后一天存钱数 (等差数列公式)
        int daysMoney = (firstDayMoney + lastDayMoney) * day / 2; // 非完整周总存钱数 (等差数列求和)

        return weeksMoney + daysMoney; // 完整周总存钱数 + 非完整周总存钱数
    }
}

上述代码也是用完整周和非完整周来做区分,但是代码没有使用任何循环操作,都是根据公式来计算结果的。 

2、排序数组

        给你一个整数数组 nums,请你将该数组升序排列。

思路:首先我们先来系统的复习回顾一下数据结构中一些基本常用的排序算法。

(1)、冒泡排序

冒泡排序是一种最基础的交换排序。之所以叫做冒泡排序,因为每一个元素都可以像小气泡一样,根据自身大小一点一点向数组的一侧移动。如图所示,可以发现虽然第三趟已经排好序了,但任需要等待第四次循环结束。上代码:

LeetCode基础算法50题Day02_第3张图片

    public int[] sortArray(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums.length-1-i; j++) {
//nums.length-1-i中-i的原因是最后一位已经确定是整个数组中最大的数了,因此不要需要再比较了
//当然使用nums.length-1,也可以实现排序,不过要多做几次没用的比较
                if (nums[j] > nums[j+1]){
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
        }
        return nums;
    }

 为了解决第三趟已经排好序了,但任需要等待第四次循环结束的问题,我对代码进行了优化改进,使用变量值来判断是否停止循环。

    public int[] sortArray(int[] nums) {
        boolean flag = true;
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums.length-1-i; j++) {
                if (nums[j] > nums[j+1]){
                    flag = false; //判断是否还存在元素交换,如果有则说明还没有排好序
                    int temp = nums[j];
                    nums[j] = nums[j+1];
                    nums[j+1] = temp;
                }
            }
            if (flag){
                break;
            }
        }
        return nums;
    }

(2)、选择排序

在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。上代码:

LeetCode基础算法50题Day02_第4张图片

    public int[] sortArray(int[] nums) {
        int smallest = 0;//最小值对应的下标
        for (int i = 0; i < nums.length-1; i++) {
//比较最后两个元素时,i只能为倒数第二个元素,因为j要比i大,所以i < nums.length-1
            smallest = i;
            for (int j = i+1; j < nums.length; j++) {
//j从i开始的原因是i前面已经排好最小的了,不用再排
                if (nums[j] < nums[smallest]){
                    smallest = j;
//如果发现有比nums[smallest]还小的数,就把下标j赋值给smallest,此时最小的数为nums[smallest](新的smallest)
                }
            }
            int temp = nums[smallest];
            nums[smallest] = nums[i];
            nums[i] = temp;
        }
        return nums;
    }

(3)、插入排序

将初始数据分为有序部分和无序部分,每次从无序部分中取出一个元素,与有序部分中的元素从后向前依次进行比较,并找到合适的位置,将该元素插到有序组当中。上代码:

LeetCode基础算法50题Day02_第5张图片

    public int[] sortArray(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
   //把第一个元素作为有序序列,则从第二个元素开始都是无序的,然后i=1拿到第二个元素
            for (int j = i-1; j >= 0 && nums[j+1] < nums[j]; j--) {
   //j=i-1:把第一个元素和第二个元素进行比较,满足nums[j+1] < nums[j],则交换,否则j--
   //内层for循环结束以后,i-->2,也就是把无序的第二个元素拿出来继续做比较
                int temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
            }
        }
        return nums;
    }

(4)、快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序。首先要寻找一个基准数,一般以第一个元素作为基准,然后把数组最左边和最右边的两个数分别作为left、right两个指针。接下来需要将这个序列中所有比基准数大的数放在右边,比基准数小的数放在左边。

LeetCode基础算法50题Day02_第6张图片

 解释:首先选出基准数19,left=19,right=8,接下来判断right=8 <19,所以应该在19左边,所以left和right的值交换、left右移、right不变;然后left继续与right比较,发现97>19,则left和right的值交换、left不变、right左移;right=1<19,left和right的值交换、left右移、right不变;left右移到9时,比right=19小,所以left继续移动;到17时,还是比19小,继续移动;最终left和right相遇,第一趟比较结束,基准数19左边都比他小,右边都比他大。接下来利用递归思想,分别对左边和右边进行快速排序。

   private static void fastSort(int[] array, int begin, int end) {
        if (begin>=end){
            return;
        }
        int target = array[begin];
        int right = end;
        int left = begin;
        while(left < right){
            while(array[right]>=target && left

如果你有不一样的思路,欢迎评论区一起讨论~

喜欢的话,可以点个赞!

你可能感兴趣的:(零基础算法50题,java,算法,leetcode)