LeetCode记录4(题目+答案+注释)难度:简单 语言:c++ && python

1、得到0的操作数

给你两个 非负 整数 num1 和 num2 。

每一步 操作 中,如果 num1 >= num2 ,你必须用 num1 减 num2 ;否则,你必须用 num2 减 num1 。

例如,num1 = 5 且 num2 = 4 ,应该用 num1 减 num2 ,因此,得到 num1 = 1 和 num2 = 4 。然而,如果 num1 = 4且 num2 = 5 ,一步操作后,得到 num1 = 4 和 num2 = 1 。
返回使 num1 = 0 或 num2 = 0 的 操作数 。

示例 1:

输入:num1 = 2, num2 = 3
输出:3
解释:
- 操作 1 :num1 = 2 ,num2 = 3 。由于 num1 < num2 ,num2 减 num1 得到 num1 = 2 ,num2 = 3 - 2 = 1 。
- 操作 2 :num1 = 2 ,num2 = 1 。由于 num1 > num2 ,num1 减 num2 。
- 操作 3 :num1 = 1 ,num2 = 1 。由于 num1 == num2 ,num1 减 num2 。
此时 num1 = 0 ,num2 = 1 。由于 num1 == 0 ,不需要再执行任何操作。
所以总操作数是 3 。

解答:

class Solution {
public:
    int countOperations(int num1, int num2) {
        int count=0;
        while(num1!=0 && num2!=0)
        {
            if(num1>num2)
            {
                count+=1;
                num1=num1-num2;
            }
            else
            {
                count+=1;
                num2=num2-num1;
            }
        }
        return count;
    }
};

参考答案:

辗转相除

class Solution {
public:
    int countOperations(int num1, int num2) {
        int res = 0;   // 相减操作的总次数
        while (num1 && num2) {
            // 每一步辗转相除操作
            res += num1 / num2;
            num1 %= num2;
            swap(num1, num2);//交换函数
        }
        return res;
    }
};

2、还原排列的最少操作步数

给你一个偶数 n​​​​​​ ,已知存在一个长度为 n 的排列 perm ,其中 perm[i] == i​(下标 从 0 开始 计数)。

一步操作中,你将创建一个新数组 arr ,对于每个 i :

如果 i % 2 == 0 ,那么 arr[i] = perm[i / 2]
如果 i % 2 == 1 ,那么 arr[i] = perm[n / 2 + (i - 1) / 2]
然后将 arr​​ 赋值​​给 perm 。

要想使 perm 回到排列初始值,至少需要执行多少步操作?返回最小的 非零 操作步数。

示例 1:

输入:n = 2
输出:1
解释:最初,perm = [0,1]
第 1 步操作后,perm = [0,1]
所以,仅需执行 1 步操作

参考答案:

class Solution {
public:
    int reinitializePermutation(int n) {
        vector<int> vec(n), next(n);
        for(int i = 0; i < n; ++i) vec[i] = i;
        for(int i = 0; i < n; ++i){
            if(i % 2 == 0) next[i] = vec[i / 2];
            else next[i] = vec[n / 2 + (i - 1) / 2];
        }
        int ans = 0, cur = 1;
        do{
            ans++;
            cur = next[cur];
        } while(cur != 1);
        return ans;
    }
};

3、是数组元素相等的减少操作次数

给你一个整数数组 nums ,你的目标是令 nums 中的所有元素相等。完成一次减少操作需要遵照下面的几个步骤:

找出 nums 中的 最大 值。记这个值为 largest 并取其下标 i (下标从 0 开始计数)。如果有多个元素都是最大值,则取最小的 i 。
找出 nums 中的 下一个最大 值,这个值 严格小于 largest ,记为 nextLargest 。
将 nums[i] 减少到 nextLargest 。
返回使 nums 中的所有元素相等的操作次数。

示例 1:

输入:nums = [5,1,3]
输出:3
解释:需要 3 次操作使 nums 中的所有元素相等:
1. largest = 5 下标为 0 。nextLargest = 3 。将 nums[0] 减少到 3 。nums = [3,1,3] 。
2. largest = 3 下标为 0 。nextLargest = 1 。将 nums[0] 减少到 1 。nums = [1,1,3] 。
3. largest = 3 下标为 2 。nextLargest = 1 。将 nums[2] 减少到 1 。nums = [1,1,1] 。

参考答案:

class Solution:
    def reductionOperations(self, nums: List[int]) -> int:
        nums.sort()
        n = len(nums)
        res = 0   # 总操作次数
        cnt = 0   # 每个元素操作次数
        for i in range(1, n):
            if nums[i] != nums[i-1]:
                cnt += 1
            res += cnt
        return res

4、三维形体的表面积

给你一个 n * n 的网格 grid ,上面放置着一些 1 x 1 x 1 的正方体。每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。

放置好正方体后,任何直接相邻的正方体都会互相粘在一起,形成一些不规则的三维形体。

请你返回最终这些形体的总表面积。

注意:每个形体的底面也需要计入表面积中。

示例 1:


输入:grid = [[1,2],[3,4]]
输出:34
示例 2:


输入:grid = [[1,1,1],[1,0,1],[1,1,1]]
输出:32

参考答案:

分步累加

class Solution:
    def surfaceArea(self, grid: List[List[int]]) -> int:
        N = len(grid)

        ans = 0
        for r in range(N):
            for c in range(N):
                if grid[r][c]:
                    ans += 2
                    for nr, nc in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
                        if 0 <= nr < N and 0 <= nc < N:
                            nval = grid[nr][nc]
                        else:
                            nval = 0

                        ans += max(grid[r][c] - nval, 0)
class Solution {
public:
    int surfaceArea(vector<vector<int>>& grid) {
        int dr[]{0, 1, 0, -1};
        int dc[]{1, 0, -1, 0};

        int N = grid.size();
        int ans = 0;

        for (int r = 0; r < N; ++r) {
            for (int c = 0; c < N; ++c) {
                if (grid[r][c] > 0) {
                    ans += 2;
                    for (int k = 0; k < 4; ++k) {
                        int nr = r + dr[k];
                        int nc = c + dc[k];
                        int nv = 0;
                        if (0 <= nr && nr < N && 0 <= nc && nc < N) {
                            nv = grid[nr][nc];
                        }

                        ans += max(grid[r][c] - nv, 0);
                    }
                }
            }
        }

        return ans;
    }
};

5、检查二进制字符串字段

给你一个二进制字符串 s ,该字符串 不含前导零 。

如果 s 包含 零个或一个由连续的 '1' 组成的字段 ,返回 true​​​ 。否则,返回 false 。

示例 1:

输入:s = "1001"
输出:false
解释:字符串中的 1 没有形成一个连续字段。
示例 2:

输入:s = "110"
输出:true

解答:

class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        n=len(s)
        for i in range(n-1):
            if(s[i]=='0' and s[i+1]=='1'):
                return False
        return True

参考答案: 

class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        return '01' not in s

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值