100天算法入门 - 每日三题 - Day17找到所有数组中消失的数最小操作次数使数组元素相等分发饼干

Posted 哪 吒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了100天算法入门 - 每日三题 - Day17找到所有数组中消失的数最小操作次数使数组元素相等分发饼干相关的知识,希望对你有一定的参考价值。

金沙滩落日


算法是进阶架构师的基础,基础不牢,地动山摇,2021-8-14起开始刷题,目标100天,300道LeetCode算法题,分享是学习的最好方式,加油,嗨起来。 

1、LeetCode 448.找到所有数组中消失的数

题目

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

小编思路

1、将数组进行排序

2、遍历数组,然后将不连续的数字添加到list中

小编菜解

/**
 * 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。
 * 请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
 *
 * 输入:nums = [4,3,2,7,8,2,3,1] -> [1,2,2,3,3,4,7,8]
 * 输出:[5,6]
 */
public static List<Integer> findDisappearedNumbers(int[] nums) {
    List<Integer> list = new ArrayList<>();
    if (nums.length == 0){
        return null;
    }
    Arrays.sort(nums);
    int n = nums.length;
    int left = 0;
    int step = 0;
    while (left < n){
        if(nums[left] == 1+step){
            left++;
        }else{
            if(nums[left] - (1+step) > 1){
                list.add(1+step+1);
            }
            step++;
        }
    }
    return list;
}

这道题没想太明白。。。

大佬指点江山

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;
        for (int num : nums) {
            int x = (num - 1) % n;
            nums[x] += n;
        }
        List<Integer> ret = new ArrayList<Integer>();
        for (int i = 0; i < n; i++) {
            if (nums[i] <= n) {
                ret.add(i + 1);
            }
        }
        return ret;
    }
}

2、LeetCode 453.最小操作次数使数组元素相等 TODO

题目

给定一个长度为 n 的 非空 整数数组,每次操作将会使 n - 1 个元素增加 1。找出让数组所有元素相等的最小操作次数。

小编思路

暴力算法,循环数组,除了最大的那个数,其它的都+1,直到最大数和最小数相等为止,不出意外会超出时间限制。

小编菜解

/**
 * 给定一个长度为 n 的 非空 整数数组,每次操作将会使 n - 1 个元素增加 1。找出让数组所有元素相等的最小操作次数。
 * [1,2,3]  =>  [2,3,3]  =>  [3,4,3]  =>  [4,4,4]
 */
public static int minMoves(int[] nums) {
    Arrays.sort(nums);
    int lg = nums.length;
    int step = 0;
    while (true){
        int min = nums[0];
        int max = nums[lg - 1];
        if (max == min){
            break;
        }
        for (int i = 0; i < lg - 1; i++) {
            nums[i] = nums[i] + 1;
        }
        step++;
        Arrays.sort(nums);
    }
    return step;
}

哈哈,果然如此,超出时间限制。

是不是arrays.sort消耗了过多的性能?改进一下

小编菜解进阶版

public static int minMoves(int[] nums) {
    int lg = nums.length;
    int step = 0;
    int max = 0;
    int min = 0;
    while (true){
        for (int i = 0; i < lg; i++) {
            if (nums[i] > max){
                max = nums[i];
            }
            if (nums[i] < min){
                min = nums[i];
            }
        }
        if (max == min){
            break;
        }
        for (int i = 0; i < lg - 1; i++) {
            nums[i] = nums[i] + 1;
        }
        step++;
    }
    return step;
}

依然超时。 

因为最大值与最小值之差,最小值想等于最大值,最小要进行max-min次+1,因此可以再次改进。

小编菜解终极版

public static int minMoves(int[] nums) {
    int step = 0;
    int min = 0;
    int max = nums.length - 1;
    while (true){
        for (int i = 0; i < nums.length; i++) {
            if (nums[max] < nums[i]){
                max = i;
            }
            if (nums[min] > nums[i]){
                min = i;
            }
        }
        int diff = nums[max] - nums[min];
        if (diff == 0){
            break;
        }
        step += diff;
        for (int i = 0; i < nums.length; i++) {
            if (i != max){
                nums[i] = nums[i] + diff;
            }
        }
    }
    return step;
}

依然超时,治标不治本,本身算法的问题。

大佬指点江山

public static int minMoves(int[] nums) {
    Arrays.sort(nums);
    int count = 0;
    for (int i = nums.length - 1; i > 0; i--) {
        count += nums[i] - nums[0];
    }
    return count;
}

 看了十分钟,硬是没看懂。先这样吧。

3、LeetCode 455.分发饼干

题目

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

小编思路

1、孩子一个数组,饼干一个数组,先按从大到小排序

2、倒序遍历饼干,倒序遍历孩子,饼干能满足孩子,则成功+1

3、当饼干遍历完毕,或者孩子遍历完毕,结束循环

小编菜解

public static int findContentChildren(int[] g, int[] s) {
    Arrays.sort(g);//孩子{1,2}
    Arrays.sort(s);//饼干{1,2,3}
    //可以分的饼干数量
    int sum = 0;
    int step = 0;
    //遍历饼干
    for (int i = s.length - 1; i >= 0; i--) {
        if ((g.length-step) > 0){
            //遍历孩子
            System.out.println("还剩孩子数:"+(g.length-1-step+1));
            for (int j = g.length-1-step; j >= 0 ; j--) {
                step++;
                //最大的饼干满足尾款最大的孩子时,完成+1
                System.out.println("饼干:"+s[i]);
                System.out.println("孩子胃口:"+g[j]);
                if(s[i] >= g[j]){
                    sum++;
                    System.out.println("分配饼干成功:"+sum);
                    break;
                }
            }
        }
    }
    return sum;
}

大佬指点江山

public int findContentChildren(int[] g, int[] s) {
    Arrays.sort(g);
    Arrays.sort(s);
    int numOfChildren = g.length, numOfCookies = s.length;
    int count = 0;
    for (int i = 0, j = 0; i < numOfChildren && j < numOfCookies; i++, j++) {
        while (j < numOfCookies && g[i] > s[j]) {
            j++;
        }
        if (j < numOfCookies) {
            count++;
        }
    }
    return count;
}

推荐阅读

【100天算法入门 - 每日三题 - Day16】第三大的数、字符串中的单词数、排列硬币

【100天算法入门 - 每日三题 - Day15】判断子序列、最长回文数、Fizz Buzz

【100天算法入门 - 每日三题 - Day14】两个数组的交集、有效的完全平方数、字符串中的第一个唯一字符

【100天算法入门 - 每日三题 - Day13】反转字符串、反转字符串中的元音字母、两个数组的交集

【100天算法入门 - 每日三题 - Day12】Nim游戏、3的幂、4的幂

【100天算法入门 - 每日三题 - Day11】丢失的数字、移动零、单词规律

【100天算法入门 - 每日三题 - Day10】二叉树的所有路径、各位相加、丑数 

【100天算法入门 - 每日三题 - Day9】汇总区间、2的幂、有效的字母异位词

【100天算法入门 - 每日三题 - Day8】同构字符串、存在重复元素、翻转二叉树

【100天算法入门 - 每日三题 - Day7】验证回文串、只出现一次的数字、多数元素

以上是关于100天算法入门 - 每日三题 - Day17找到所有数组中消失的数最小操作次数使数组元素相等分发饼干的主要内容,如果未能解决你的问题,请参考以下文章

100天算法入门 - 每日三题 - Day12Nim游戏3的幂4的幂

100天算法入门 - 每日三题 - Day15判断子序列最长回文数Fizz Buzz

100天算法入门 - 每日三题 - Day5最后一个单词的长度相同的树买卖股票的最佳时机

100天算法入门 - 每日三题 - Day16第三大的数字符串中的单词数排列硬币

100天算法入门 - 每日三题 - Day10二叉树的所有路径各位相加丑数

100天算法入门 - 每日三题 - Day13反转字符串反转字符串中的元音字母两个数组的交集