LeetCode 507. 完美数 / 2022. 将一维数组转变成二维数组 / 390. 消除游戏(等差数列模拟,约瑟夫环)

507. 完美数

2021.12.31 每日一题,年底最后一题,祝大家新年快乐

题目描述

对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」。

给定一个 整数 n, 如果是完美数,返回 true,否则返回 false

示例 1:

输入:num = 28
输出:true
解释:28 = 1 + 2 + 4 + 7 + 14
1, 2, 4, 7, 和 14 是 28 的所有正因子。

示例 2:

输入:num = 6
输出:true

示例 3:

输入:num = 496
输出:true

示例 4:

输入:num = 8128
输出:true

示例 5:

输入:num = 2
输出:false

提示:

1 <= num <= 10^8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution {
    public boolean checkPerfectNumber(int num) {
        //相当于找因子
        if(num < 2)
            return false;
        int range = (int)Math.sqrt(num);
        int res = 1;
        for(int i = 2; i <= range; i++){
            if(num % i == 0){
                res += i + num / i;
            }
        }
        return num == res;
    }
}

2022. 将一维数组转变成二维数组

2022.1.1 每日一题 新年快乐啊!!!!!

题目描述

给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n 。你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。

original 中下标从 0 到 n - 1 (都 包含 )的元素构成二维数组的第一行,下标从 n 到 2 * n - 1 (都 包含 )的元素构成二维数组的第二行,依此类推。

请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。

示例 1:

在这里插入图片描述
输入:original = [1,2,3,4], m = 2, n = 2
输出:[[1,2],[3,4]]
解释:
构造出的二维数组应该包含 2 行 2 列。
original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。
original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。

示例 2:

输入:original = [1,2,3], m = 1, n = 3
输出:[[1,2,3]]
解释:
构造出的二维数组应该包含 1 行 3 列。
将 original 中所有三个元素放入第一行中,构成要求的二维数组。

示例 3:

输入:original = [1,2], m = 1, n = 1
输出:[]
解释:
original 中有 2 个元素。
无法将 2 个元素放入到一个 1x1 的二维数组中,所以返回一个空的二维数组。

示例 4:

输入:original = [3], m = 1, n = 2
输出:[]
解释:
original 中只有 1 个元素。
无法将 1 个元素放满一个 1x2 的二维数组,所以返回一个空的二维数组。

提示:

1 <= original.length <= 5 * 10^4
1 <= original[i] <= 10^5
1 <= m, n <= 4 * 10^4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-1d-array-into-2d-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution {
    public int[][] construct2DArray(int[] original, int m, int n) {
        //2022年第一道题是2022题
        int l = original.length;
        if(l != m * n)
            return new int[][]{};
        int[][] ans = new int[m][n];
        int idx = 0;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                ans[i][j] = original[idx++];
            }
        }
        return ans;
    }
}

390. 消除游戏

2022.1.2 每日一题

题目描述

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:

从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
给你整数 n ,返回 arr 最后剩下的数字。

示例 1:

输入:n = 9
输出:6
解释:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]

示例 2:

输入:n = 1
输出:1

提示:

1 <= n <= 10^9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/elimination-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这个等差数列的好理解

class Solution {
    public int lastRemaining(int n) {
        //先删除1 3 5 7 9
        //找了下规律,先删除2倍的,再四倍的,再8倍
        //刚开始是奇数删掉,然后看从哪个数字开始,每隔4删除一次,然后是每隔8
        //所以记录左右的起始位置就可以了

        //然后发现不会记,总感觉会漏掉值
        //然后看了题解,发现只需要统计左边第一个数就行了
        int left = 1;
        int base = 1;
        int k = 0;
        int count = n;
        
        while(count > 1){
            //从左到右删除,那么删除以后,最左边的数就是第二个数
            if(k % 2 == 0){
                left = left + base;
            }else{
                //如果当前数目是偶数,那么左边不会删除;如果是奇数,那么左边会删除,而下一个位置也是加base
                if(count % 2 == 1){
                    left = left + base;
                }
            }
            base <<= 1;
            count >>= 1;
            k++;
        }
        return left;
    }
}

约瑟夫环公式推导问题
从左到右删除,剩下的数定义为a,f[i]
从右到左删除,剩下的数定义为b, g[i]
总数为i,那么a + b = n + 1,f[i] + g[i] = i + 1

然后和约瑟夫环一样,刚开始删除奇数,也就是1 3 5 7…得到了f[i]
此时,剩下g[i/2],同时f[i] = 2 * g[i / 2]
代入上面的第一个公式,得到f[i] = 2 * (i / 2 + 1 - f[i / 2] )

然后就可以使用递归的思想,得到最后的结果
挺难的,不好想

class Solution {
    public int lastRemaining(int n) {
        return n == 1 ? 1 : 2 * (n / 2 + 1 - lastRemaining(n / 2));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值